私が使う SQL Server 2008 R2
。
2つの列の最小値でテーブルをソートする必要があります。
テーブルは次のようになります。
ID: integer;
Date1: datetime;
Date2: datetime.
データを最低2つの日付で並べ替えたい。
このテーブルをそのように並べ替える最も簡単な方法は何ですか?
NOT NULLカラム。 [〜#〜] case [〜#〜]ステートメントをORDER BY句に追加する必要があります:
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
WHEN Date1 < Date2 THEN Date1
ELSE Date2
END
NULLABLE列。 Zohar Peledが列がnull可能である場合にコメントに書き込んだように、ISNULL
を使用できます(ただし、COALESCE
の代わりにISNULL
を使用することをお勧めします、これはANSI SQL standard
)であるためです。
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
WHEN COALESCE(Date1, '1753-01-01') < COALESCE(Date2, '1753-01-01') THEN Date1
ELSE Date2
END
[〜#〜] ansi [〜#〜]標準の日付形式1753-01-01
here について読むことができます。
_ORDER BY
_でCASE
式を使用します。
_ ORDER BY case when date1 < date2 then date1 else date2 end
_
編集:
null値を考慮する必要がある場合は、coalesce()
を追加します。
_ ORDER BY case when date1 < date2 then date1 else coalesce(date2,date1) end
_
説明:
Date1 <date2の場合、date1で並べ替えます。 (ここではどちらの日付もnullではありません。)以前と同じように機能します。
そうでない場合は、COALESCE()
を使用して、date2(date2がnullでない場合)、またはdate1(date2がnullの場合)、またはnull(両方の日付がnullの場合)の順に並べます。
最も簡単な方法は、次のように VALUES
キーワードを使用することです。
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY (SELECT MIN(v) FROM (VALUES (Date1), (Date2)) AS value(v))
このコードは、nullable列でも、すべてのケースで機能します。
編集:
ソリューション でCOALESCE
キーワードを使用すると、普遍的ではありません。これには重要な制限があります。
Date
タイプの場合は機能しません(01/01/1753
より前の日付を使用する場合)NULL
の場合は機能しません。 NULL
値を最小のdatetime
値として解釈します。しかし、それは本当ですか? datetime
でもなく、何もありません。IF
式はさらに複雑になります。質問によると:
このテーブルをそのようにソートする最も簡単な方法は何ですか?
最短かつ最も簡単な解決策は、上記の解決策です。
Date
列で機能します。コードを変更する必要はありません。編集2:
Zohar Peledは、次の順序を提案しました。
私はこのルールで行を並べ替えます:最初に、両方がnullの場合、2番目、date1がnullの場合、3番目、date 2がnullの場合、4番目、min(date1、date2)
したがって、この場合、次のような同じアプローチを使用してソリューションに到達できます。
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY
CASE WHEN Date1 IS NULL AND Date2 IS NULL THEN 0
WHEN Date1 IS NULL THEN 1
WHEN Date2 IS NULL THEN 2
ELSE 3 END,
(SELECT MIN(v) FROM (VALUES ([Date1]), ([Date2])) AS value(v))
このコードの出力は次のとおりです。
COALESCE
solutionは、この方法でテーブルをソートしません。それはmesses upNULL
値の少なくとも1つのセルがある行。その出力は次のとおりです。
これが役に立ち、批評家を待つことを願っています。
これは、_CASE WHEN
_のように分岐を必要としない代替ソリューションの可能性があります。これは、式max(a,b)=1/2(a+b+|a−b|)
ここ に基づいています。 DATEDIFF
と参照日付(_'1773-01-01'
_)を使用して、aとbの絶対値を取得します。
_ORDER BY (DATEDIFF(d,'17730101' ,isnull(Startdate,enddate)) + DATEDIFF(d,'17730101' ,isnull(EndDate,Startdate))
- ABS(DATEDIFF(d,isnull(Startdate,enddate),isnull(EndDate,Startdate))))
_
テストデータ
_Create Table #DateData(ID int Identity, Name varchar(15),Startdate datetime,EndDate DateTime)
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-19 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-20 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-11 18:48:27','2015-04-22 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-05-09 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 19:07:38','2015-04-17 18:55:38')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 19:07:38','2015-05-12 18:56:29')
_
完全なクエリ
_select *
from #DateData order by (DATEDIFF(d,'17730101' ,isnull(Startdate,enddate)) + DATEDIFF(d,'17730101' ,isnull(EndDate,Startdate))
- ABS(DATEDIFF(d,isnull(Startdate,enddate),isnull(EndDate,Startdate))))
_
Case statement
でOrder By
を使用しない場合は、Case statement
をSelect
に移動するだけの別のアプローチです。
SELECT Id, Date1, Date2 FROM
(SELECT Id, Date1, Date2
,CASE WHEN Date1 < Date2 THEN Date1 ELSE Date2 END as MinDate
FROM YourTable) as T
ORDER BY MinDate
私はCROSS APPLY
を使用していますが、パフォーマンスについてはわかりませんが、私の経験ではCROSS APPLY
の方がパフォーマンスが優れていることがよくあります。
CREATE TABLE #Test (ID INT, Date1 DATETIME, Date2 DATETIME)
INSERT INTO #Test SELECT 1, NULL, '1/1/1';INSERT INTO #Test SELECT 2, NULL, NULL;INSERT INTO #Test SELECT 3, '2/2/2', '3/3/1';INSERT INTO #Test SELECT 4, '3/3/3', '11/1/1'
SELECT t.ID, Date1, Date2, MinDate
FROM #TEST t
CROSS APPLY (SELECT MIN(d) MinDate FROM (VALUES (Date1), (Date2)) AS a(d)) md
ORDER BY MinDate
DROP TABLE #Test
私はこの方法でnull許容列を処理することを好みます。
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY
CASE
WHEN Date1 < Date2 OR Date1 IS NULL THEN Date1
ELSE Date2
END
howからフォーカスをwhyに変更します。これが必要です-代わりにスキーマを変更することを提案します。経験則は次のとおりです。データにアクセスするためにスタントをプルする必要がある場合、設計上の決定は不適切です。
ご覧のように、このタスクはSQLでは非常に一般的ではないため、可能ではありますが、提案されたすべてのメソッドは通常のORDER BY
。
date1
とdate2
の両方のフィールドで並べ替える場合は、次のようにORDER BY
の部分に両方を含める必要があります。
SELECT *
FROM aTable
ORDER BY
CASE WHEN date1 < date2 THEN date1
ELSE date2 END,
CASE WHEN date1 < date2 THEN date2
ELSE date1 END
結果は次のようになります。
date1 | date2
-----------+------------
2015-04-25 | 2015-04-21
2015-04-26 | 2015-04-21
2015-04-25 | 2015-04-22
2015-04-22 | 2015-04-26
Null
値を使用して完全な結果を得るには、以下を使用します。
SELECT *
FROM aTable
ORDER BY
CASE
WHEN date1 IS NULL THEN NULL
WHEN date1 < date2 THEN date1
ELSE date2 END
,CASE
WHEN date2 IS NULL THEN date1
WHEN date1 IS NULL THEN date2
WHEN date1 < date2 THEN date2
ELSE date1 END
結果は次のようになります。
date1 | date2
-----------+------------
NULL | NULL
NULL | 2015-04-22
2015-04-26 | NULL
2015-04-25 | 2015-04-21
2015-04-26 | 2015-04-21
2015-04-25 | 2015-04-22
私はこのルールで行を並べます:
これを行うには、ネストされたケースが単純で効率的です(テーブルが非常に大きい場合を除く) この投稿によると 。
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY
CASE
WHEN Date1 IS NULL AND Date2 IS NULL THEN 0
WHEN Date1 IS NULL THEN 1
WHEN Date2 IS NULL THEN 2
ELSE 3 END,
CASE
WHEN Date1 < Date2 THEN Date1
ELSE Date2
END
別のオプションがあります。必要なロジックによって結果列を計算し、列による順序付けで外部列による選択をカバーできます。この場合、コードは次のようになります。
select ID, x.Date1, x.Date2
from
(
select
ID,
Date1,
Date2,
SortColumn = case when Date1 < Date2 then Date1 else Date2 end
from YourTable
) x
order by x.SortColumn
このソリューションの利点は、必要なフィルタリングクエリを(内部選択で)追加でき、それでもインデックスが役立つことです。
_order by
_句でmin
関数を使用できます。
_select *
from [table] d
order by ( select min(q.t) from (
select d.date1 t union select d.date2) q
)
_
_order by
_句でcase
ステートメントを使用することもできますが、(_>
_および_<
_)の任意の値(nullまたはnone null)とnullを比較した結果はtrue
ではありません。 _ansi_nulls
_をoff
に設定しました。したがって、目的の並べ替えを保証するには、null
句でわかっているように、case
の結果がwhen
である場合はtrue
ステートメントを評価しないため、when
sを処理する必要があります。
_select * from [table]
order by case
when date1 is null then date2
when date2 is null then date1
when date1<date2 then date1 -- surely date1 and date2 are not null here
else date2
end
_
また、シナリオが異なる場合のその他の解決策もいくつかあります。おそらく、別のフィールド内の複数の列(または計算)を比較した結果を評価し、最後に、order by句内の条件を使用せずに、その計算済みフィールドで並べ替えます。
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY (SELECT TOP(1) v FROM (VALUES (Date1), (Date2)) AS value(v) ORDER BY v)
@dyatchenkoの回答に非常に似ていますが、NULLの問題はありません