日時フィールドのあるSQLテーブルがあります。問題のフィールドはnullにすることができます。クエリがあり、日時フィールドで結果を昇順に並べ替えたいが、日時フィールドがリストの最初ではなく最後にnullである行が欲しい。
それを達成する簡単な方法はありますか?
日時フィールドのあるSQLテーブルがあります。問題のフィールドはnullにすることができます。クエリがあり、日時フィールドで結果を昇順に並べ替えたいが、日時フィールドがリストの最初ではなく最後にnullである行が欲しい。
それを達成する簡単な方法はありますか?
回答:
select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate
order by case when MyDate is null then 1 else 0 end
言い方は本当に長いですORDER BY MyDate IS NULL
order by 0
は列インデックスとして解釈されるため、列インデックスは1 から始まります。クエリを3番目の列で並べ替えるにはorder by 3
(プロダクションクエリではひどい考えです)と言えますが、試してみると非常に便利です(そのままです*
)。
(「少し」遅くなりますが、これはまったく言及されていません)
DBMSを指定していません。
標準のSQL(とOracle、PostgreSQLの、DB2、Firebirdの、Apache Derbyを、HSQLDBやH2などの最も近代的なDBMS)で次のように指定することができますNULLS LAST
かNULLS FIRST
。
NULLS LAST
それらを最後にソートするために使用します:
select *
from some_table
order by some_column DESC NULLS LAST
NULLS FIRST
およびNULLS LAST
はSQL:2003で追加されましたが、さまざまなDMBS全体で使用できる標準実装はありません。データベースエンジンに応じて、ORDER BY expr some_column DESC NULLS LAST
(Oracle)、ORDER BY ISNULL(some_column, 1), some_column ASC
(MSSQL)、またはORDER BY ISNULL(some_column), some_column ASC
(別のISNULL()実装のMySQL)を使用します。
ASC
/ DESC
一部が行うヌルで。したがって、これを確実にする唯一の方法は、DBMSがサポートしているNULL FIRST/LAST
場合に使用することです。それであなたが意図していることを文書化します。isnull()
またはその他の関数の使用は、欠落しているサポートの回避策ですNULLS FIRST/LAST
(Oracle、PostgreSQL、DB2、Firebird、Apache Derby、HSQLDBおよびH2でサポートされています)
expr
NULLS FIRST / LASTを使用するときにキーワードを必要とするOracleのような彼らの専門があるかなりのDBMSがあるという事実を追加したかっただけです。そして、データベースのタイプごとに最初と最後に異なるnullが表示されることについて感謝します。
NULLS LAST
ましたが、MySQLデータベースでは機能しませんでした。
私はこれにも偶然遭遇しましたが、MySQLとPostgreSQLでは次のようにうまくいくようです。
ORDER BY date IS NULL, date DESC
IS NULL
し、IS NOT NULL
私のMySQLデータベースでは動作しませんでした。
order by coalesce(date-time-field,large date in future)
次のように、組み込み関数を使用してnullかどうかをチェックできます。私はそれとその動作をテストしました。
select MyDate from MyTable order by ISNULL(MyDate,1) DESC, MyDate ASC;
ISNULL(MyDate) DESC, MyDate ASC
ましたが、正しい順序で並べ替えられませんでした。
エンジンが許可する場合、ORDER BY x IS NULL, x
またはORDER BY x NULLS LAST
使用している場合。しかし、それが役に立たない場合は、次の方法が役立つ可能性があります。
数値タイプで並べ替える場合は、次のようにできます(別の回答からスキーマを借用します)。
SELECT *
FROM Employees
ORDER BY ISNULL(DepartmentId*0,1), DepartmentId;
null以外の数値はすべて0になり、nullは1になり、nullは最後にソートされます。
文字列に対してこれを行うこともできます。
SELECT *
FROM Employees
ORDER BY ISNULL(LEFT(LastName,0),'a'), LastName
なぜなら'a'
> ''
。
これは、null許容のintに強制変換し、上記のintのメソッドを使用することにより、日付でも機能します。
SELECT *
FROM Employees
ORDER BY ISNULL(CONVERT(INT, HireDate)*0, 1), HireDate
(スキーマにHireDateがあると仮定します。)
これらのメソッドは、データタイプ(および最大値)が変更された場合に、すべてのタイプの「最大」値を考え出すか管理するか、クエリを修正する必要があるという問題を回避します(他のISNULLソリューションが抱える問題の両方)。さらに、CASEよりもはるかに短いです。
注文列が数値(ランクなど)の場合、-1を掛けてから降順で並べ替えることができます。それはあなたが期待している注文を維持しますが、最後にNULLを置きます。
select *
from table
order by -rank desc
SELECT *
FROM Employees
ORDER BY ISNULL(DepartmentId, 99999);
こちらのブログ投稿をご覧ください。
null可能な日付時刻フィールドの並べ替えのバグの問題に対する優れたソリューションを提供してくれたRedFilterに感謝します。
プロジェクトにSQL Serverデータベースを使用しています。
datetimeのnull値を「1」に変更すると、datetimeデータ型列の並べ替えの問題が解決されます。ただし、datetimeデータ型以外の列がある場合は、処理に失敗します。
varchar列の並べ替えを処理するために、「ZZZZZZZ」を使用してみました。列に「Z」で始まる値がないことがわかっているためです。期待通りに動きました。
同じ行で、intおよびその他のデータ型に最大値+1を使用して、期待どおりに並べ替えを行いました。これにより、必要な結果も得られました。
ただし、データベースエンジン自体で次のようなことを実行できる簡単なものを取得することが常に理想的です。
Order by Col1 Asc Nulls Last, Col2 Asc Nulls First
a_horse_with_no_nameが提供する回答で述べたように。
Oracleでは、NULLS FIRST
orまたはNULLS LAST
:を使用して、非NULL値の前/後にNULL値を返すように指定します。
ORDER BY { column-Name | [ ASC | DESC ] | [ NULLS FIRST | NULLS LAST ] }
例えば:
ORDER BY date DESC NULLS LAST
参照:http : //docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj13658.html
MariaDBを使用している場合、NULL値のドキュメントで次のように述べられています。
ご注文
NULL値を含む可能性のあるフィールドで並べ替えると、NULLは最も低い値を持つと見なされます。したがって、DESC順に並べ替えると、NULLが最後に表示されます。NULLを最も高い値と見なすようにするには、メインフィールドがNULLのときに、より高い値を持つ別の列を追加します。例:
SELECT col1 FROM tab ORDER BY ISNULL(col1), col1;
降順、最初にNULLを使用:
SELECT col1 FROM tab ORDER BY IF(col1 IS NULL, 0, 1), col1 DESC;
すべてのNULL値は、DISTINCT句とGROUP BY句の目的でも同等と見なされます。
上記はNULL値による順序付けの2つの方法を示しています。これらをASCおよびDESCキーワードと組み合わせることもできます。たとえば、最初にNULL値を取得する別の方法は次のとおりです。
SELECT col1 FROM tab ORDER BY ISNULL(col1) DESC, col1;
-- ^^^^
「ケース」を使用した解決策は一般的ですが、インデックスを使用しないでください。
order by case when MyDate is null then 1 else 0 end, MyDate
私の場合、パフォーマンスが必要でした。
SELECT smoneCol1,someCol2
FROM someSch.someTab
WHERE someCol2 = 2101 and ( someCol1 IS NULL )
UNION
SELECT smoneCol1,someCol2
FROM someSch.someTab
WHERE someCol2 = 2101 and ( someCol1 IS NOT NULL)
UNION ALL
。
USE NVL関数
select * from MyTable order by NVL(MyDate, to_date('1-1-1','DD-MM-YYYY'))