web-dev-qa-db-ja.com

同じSELECTステートメントでDISTINCTとORDER BYを使用する方法は?

次のステートメントを実行した後:

SELECT  Category  FROM MonitoringJob ORDER BY CreationDate DESC

データベースから次の値を取得しています:

test3
test3
bildung
test4
test3
test2
test1

しかし、私は次のように重複を削除したい:

bildung
test4
test3
test2
test1

DISTINCTを使用しようとしましたが、1つのステートメントでORDER BYが機能しません。助けてください。

重要:

  1. 私はそれを試しました:

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC
    

    機能しません。

  2. CreationDateによる順序は非常に重要です。

93
r.r

問題は、ORDER BYで使用される列がDISTINCTで指定されていないことです。これを行うには、 集計関数 を使用してソートし、GROUP BYを使用してDISTINCTを機能させる必要があります。

次のようなものを試してください:

SELECT DISTINCT Category, MAX(CreationDate) 
FROM MonitoringJob 
GROUP BY Category 
ORDER BY MAX(CreationDate) DESC, Category
156
Prutswonder

拡張ソートキー列

何をしたいのかがうまくいかない理由は、 SQLの操作の論理的な順序 のためです。

  • FROM MonitoringJob
  • SELECT Category, CreationDateつまり、いわゆる拡張ソートキー列を追加します
  • ORDER BY CreationDate DESC
  • SELECT Categoryつまり、結果から拡張ソートキー列を再度削除します。

そのため、SQL標準拡張ソートキー列機能のおかげで、SELECT句にないもので並べ替えることができます。一時的にバックグラウンドで追加されます。

では、なぜDISTINCTでこれが機能しないのでしょうか?

DISTINCT操作を追加すると、SELECTORDER BYの間に追加されます。

  • FROM MonitoringJob
  • SELECT Category, CreationDate
  • DISTINCT
  • ORDER BY CreationDate DESC
  • SELECT Category

しかし、拡張ソートキー列CreationDateでは、DISTINCT操作のセマンティクスが変更されたため、結果は同じではなくなりました。これは私たちが望んでいるものではないため、SQL標準とすべての妥当なデータベースの両方がこの使用を禁止しています。

回避策

次のような標準構文でエミュレートできます

SELECT Category
FROM (
  SELECT Category, MAX(CreationDate) AS CreationDate
  FROM MonitoringJob
  GROUP BY Category
) t
ORDER BY CreationDate DESC

または、 Prutswonder で示されるように、単に(この場合)

SELECT Category, MAX(CreationDate) AS CreationDate
FROM MonitoringJob
GROUP BY Category
ORDER BY CreationDate DESC

ここでSQL DISTINCTとORDER BYの詳細をブログに書いています

9
Lukas Eder

元の質問の例のように、MAX(Cre​​ationDate)の出力が必要ない場合、唯一の答えはPrashant Guptaの答えの2番目のステートメントです。

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

説明:インライン関数でORDER BY句を使用することはできません。そのため、Prutwonderの答えのステートメントはこの場合は使用できません。外側の選択をその周囲に配置して、MAX(Cre​​ationDate)部分を破棄することはできません。

4
Marc_Sei

[Category]列と[CreationDate]列の値が必要な場合は、このコードを使用してください

SELECT [Category], MAX([CreationDate]) FROM [MonitoringJob] 
             GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

または、[Category]列の値のみが必要な場合は、このコードを使用します。

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

必要なものはすべて、個別のレコードになります。

2
Prashant Gupta

2)CreationDateによる順序は非常に重要です

元の結果は、「test3」に複数の結果があることを示していました...

Group Byの重複を削除するために常にMAXの使用を開始するのは非常に簡単です...そして、根本的な質問が何であるかを忘れるか無視します...

OPは、MAXを使用すると最後の「作成済み」が提供され、MINを使用すると最初の「作成済み」が提供されることに気付いたと思われます...

1
JohnSurrey
if object_id ('tempdb..#tempreport') is not null
begin  
drop table #tempreport
end 
create table #tempreport (
Category  nvarchar(510),
CreationDate smallint )
insert into #tempreport 
select distinct Category from MonitoringJob (nolock) 
select * from #tempreport  ORDER BY CreationDate DESC
0
Bob

Distinctは、レコードを昇順でソートします。降順でソートする場合は、次を使用します

SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC

CreationDateフィールドに基づいてレコードをソートする場合、このフィールドはselectステートメントに含まれている必要があります。

SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC
0
C Patel

サブクエリによって、それは動作するはずです:

    SELECT distinct(Category) from MonitoringJob  where Category in(select Category from MonitoringJob order by CreationDate desc);

CTEを使用できます。

WITH DistinctMonitoringJob AS (
    SELECT DISTINCT Category Distinct_Category FROM MonitoringJob 
)

SELECT Distinct_Category 
FROM DistinctMonitoringJob 
ORDER BY Distinct_Category DESC
0
Jair