none
ソートするカラムに【null】が含まれる場合の扱いについて RRS feed

  • 質問

  • こんにちわ!
    お世話になります。

    Linq to SQL を使って、目的レコードの抽出を行っていますが、その際に
    orderby によりソーティングをしています。

    そこで、例えば 日付のカラムで昇順にソートする場合、その一部レコードの
    日付カラムに【null】が設定されていると、【null】のレコードが先に並びます。

    これを、昇順に並ぶレコードの後に、日付カラムが【null】のレコードが続く
    ようにしたいのですが、どうすれば宜しいのでしょうか。

    【null】のカラムをうまく扱う方法をご教授下さい。
    宜しくお願い致します。

    2011年6月8日 4:45

回答

  • すなおに、ソート条件に null 判定を加えればよいのではないですか?

          using (var db = new DataContext2())
          {
            db.Log = Console.Error;
    
            var query = from t2 in db.Table2
                  orderby t2.day == null, t2.day
                  select new { t2.day, t2.id };
    
            foreach (var row in query)
              Console.WriteLine("{0,10:yyyy/MM/dd}, {1}", row.day, row.id);
    
            Console.ReadKey();
          }
    
    /*
    SELECT [t0].[day], [t0].[id]
    FROM [dbo].[Table2] AS [t0]
    ORDER BY
      (CASE WHEN [t0].[day] IS NULL THEN 1 ELSE 0 END), [t0].[day]
    
    2010/03/03, 1
    2011/01/01, 5
    2011/04/10, 3
         , 4
         , 2
    
    */
    

    もしくはデフォルト値を与えるとか、

    // 日付が NULL の場合は MaxValue にして最後にまとめる
    order by t2.day ?? DateTime.MaxValue, t2.id
    
    
    2011年6月8日 5:18
  • orderby は指定された項目の順に並べます。

    orderby t.Year, t.Month, t.Day;

    とすると、t.Year でソート → t.Year が同じ場合 t.Month でソート → t.Month まで同じ場合 t.Day でソート なので、年月日順に並びます。ソート順序に bool を指定した場合、false → true の順に並びます。(これは、出力された SQL から、真を 1 偽を 0 として処理しているためであることがわかりますが、Linq2SQL に限らず、bool 型のソート順は false → true です。)

    2011年6月8日 8:18

すべての返信

  • すなおに、ソート条件に null 判定を加えればよいのではないですか?

          using (var db = new DataContext2())
          {
            db.Log = Console.Error;
    
            var query = from t2 in db.Table2
                  orderby t2.day == null, t2.day
                  select new { t2.day, t2.id };
    
            foreach (var row in query)
              Console.WriteLine("{0,10:yyyy/MM/dd}, {1}", row.day, row.id);
    
            Console.ReadKey();
          }
    
    /*
    SELECT [t0].[day], [t0].[id]
    FROM [dbo].[Table2] AS [t0]
    ORDER BY
      (CASE WHEN [t0].[day] IS NULL THEN 1 ELSE 0 END), [t0].[day]
    
    2010/03/03, 1
    2011/01/01, 5
    2011/04/10, 3
         , 4
         , 2
    
    */
    

    もしくはデフォルト値を与えるとか、

    // 日付が NULL の場合は MaxValue にして最後にまとめる
    order by t2.day ?? DateTime.MaxValue, t2.id
    
    
    2011年6月8日 5:18
  • K. Takaoka さま、有り難うございます。

    教えて頂いた記述を行うと、旨く行く事が確認できました。

    しかし、【orderby t2.day == null, t2.day】の構文は初めて見たもので
    その意味はまだ理解できていません。

    あと、【デフォルト値を与える】もまだ試せていませんが、先の方法と共に、
    勉強してみます。

    まずは、問題解決のご報告とお礼です。

    これをもちまして、クローズさせて頂きます。

    2011年6月8日 6:28
  • orderby は指定された項目の順に並べます。

    orderby t.Year, t.Month, t.Day;

    とすると、t.Year でソート → t.Year が同じ場合 t.Month でソート → t.Month まで同じ場合 t.Day でソート なので、年月日順に並びます。ソート順序に bool を指定した場合、false → true の順に並びます。(これは、出力された SQL から、真を 1 偽を 0 として処理しているためであることがわかりますが、Linq2SQL に限らず、bool 型のソート順は false → true です。)

    2011年6月8日 8:18
  • K. Takaoka さま、色々と有り難うございます。

    並び順に【bool】を指定できる事を知りませんでした。

    お陰様で、一歩進む事ができました。
    これからも、どうぞ宜しくお願い致します。

    2011年6月8日 9:05