8

特定のフォーマット規則を満たすデータベースから最大値を見つける必要があります。具体的には、次のような最高の値を見つけたいと思います

EU999999(「9」は任意の数字)

select max(col)は、たとえば除外したい「EUZ...」のようなものを返します。次のクエリでうまくいきますが、Linq-to-SQLを介してこれを生成することはできません。SQL Serverのisnumeric()関数の変換はないようです。

select max(col) from table where col like 'EU%' 
    and 1=isnumeric(replace(col, 'EU', ''))

このテーブルは私のアプリの中心であり、テーブルオブジェクトを他のものに簡単に置き換えることができないため、データベース関数、ストアドプロシージャ、またはそのような性質のものを作成することは、私の好ましいソリューションのリストのはるか下にあります。

次善の解決策は何ですか?

4

4 に答える 4

13

欠落していISNUMERICますが、ほぼ同等のものをいつでも試すことができますNOT LIKE '%[^0-9]%。つまり、文字列に数字以外の文字列がないか、文字列が空であるか、数字のみで構成されています。

from x in table 
where SqlMethods.Like(x.col, 'EU[0-9]%') // starts with EU and at least one digit
  && !SqlMethods.Like(x.col, '__%[^0-9]%') // and no non-digits
select x;

もちろん、桁数が固定されていることがわかっている場合は、これを次のように簡略化できます。

from x in table 
where SqlMethods.Like(x.col, 'EU[0-9][0-9][0-9][0-9][0-9][0-9]')
select x;
于 2010-02-24T21:35:53.033 に答える
11

ISNUMERICDataContextの部分クラスにメソッドを追加することで、この関数を利用できます。これは、UDFを使用する場合と似ています。

DataContextの部分クラスに次を追加します。

partial class MyDataContext
{
    [Function(Name = "ISNUMERIC", IsComposable = true)]
    public int IsNumeric(string input)
    {
        throw new NotImplementedException(); // this won't get called
    }
}

次に、コードは次のように使用します。

var query = dc.TableName
              .Select(p => new { p.Col, ReplacedText = p.Col.Replace("EU", "") })
              .Where(p => SqlMethods.Like(p.Col, "EU%")
                        && dc.IsNumeric(p.ReplacedText) == 1)
              .OrderByDescending(p => p.ReplacedText)
              .First()
              .Col;

Console.WriteLine(query);

または、MAXを使用することもできます。

var query = dc.TableName
              .Select(p => new { p.Col, ReplacedText = p.Col.Replace("EU", "") })
              .Where(p => SqlMethods.Like(p.Col, "EU%")
                  && dc.IsNumeric(p.ReplacedText) == 1);

var result = query.Where(p => p.ReplacedText == query.Max(p => p.ReplacedText))
                  .First()
                  .Col;

Console.WriteLine("Max: {0}, Result: {1}", max, result);

最終的な目標によっては、max変数で停止し、「EU」テキストを前に付けて、列名を取得する2番目のクエリを回避できる場合があります。

編集:コメントで述べたように、このアプローチの欠点は、順序付けが数値ではなくテキストで行われ、現在Int32.ParseSQLでの翻訳がないことです。

于 2010-02-24T22:47:12.687 に答える
1

あなたが言ったように、LINQからSQLへのIsNumericの翻訳はありません。いくつかのオプションがあります。すでにデータベース関数とストアドプロシージャを書き留めています。もう2つ追加したいです。

オプション1:LINQtoSQLとLINQtoObjectsを混合することでこれを行うことができますが、大きなデータベースがある場合は、優れたパフォーマンスを期待しないでください。

var cols = (from c in db.Table where c.StartsWith("EU") select c).ToList();
var stripped = from c in cols select int.Parse(c.Replace("EU", ""));
var max = stripped.Max();

オプション2:データベーススキーマを変更します:-)

于 2010-02-24T21:39:01.340 に答える
0

私の提案は、インラインSQLにフォールバックし、DataContext.ExecuteQuery()メソッドを使用することです。最初に投稿したSQLクエリを使用します。

これは私が同様の状況で行ったことです。タイプチェックがなく、構文エラーが発生する可能性があるため、理想的ではありませんが、ユニットテストに含まれていることを確認してください。考えられるすべてのクエリがLinq構文でカバーされているわけではないため、そもそもExecuteQueryが存在します。

于 2010-06-09T23:44:37.427 に答える