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


116

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

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による注文は非常に重要です。


1
どのように機能しないのですか?間違った出力?
Fedearne、2011年

回答:


194

問題は、で使用される列ORDER BYがで指定されていないことDISTINCTです。これを行うには、集計関数を使用して並べ替え、a GROUP BYを使用してDISTINCT作業を行う必要があります。

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

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

98
カテゴリでグループ化している場合は、DISTINCTキーワードも必要ありません。
MatBailie

18

拡張ソートキー列

あなたがしたいことがうまくいかない理由は、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について詳しくは、こちらのブログを参照してください


1
私はあなたがどのようにDISTINCT ON機能するのか間違っていると思います、そしてそれがここでは役に立たないと確信しています。括弧内の表現は、区別(グループ化条件)を決定するために使用されるものです。同じカテゴリが複数ある場合CreationDate、結果にはそれらの1つだけが表示されます。どういうわけか私が間違っているのではないかと思っていたので、ブログのサンプルデータベースを読み込んで再確認しました。DISTINCT ONそこで行ったクエリでは、合計1000件の結果(大量の重複lengths)が生成されましたが、その下のクエリでは唯一の140(一意の)値。
インクリング

@Inkling:お時間をいただきありがとうございます。OPは明示的に「重複」の削除を望んでいます。OPの「このように重複を削除したい」という表現を参照してください。私のブログ投稿からクエリをコピーしたときに、おそらく間違いを犯したでしょう。2つのクエリがあり、1つはDISTINCT(no ON)を使用し、もう1つはを使用しDISTINCT ONます。後者は重複した長さを削除せず、重複したタイトルを削除することに注意してください。ここでの私の答えは完全に正しいと思います。
Lukas Eder、

1
私のポイントは、あなたのDISTINCT ON条件は間違った条件を使用して重複を削除しているということです。ブログ投稿でDISTINCT ONは実際に重複するタイトルを削除しますが、その上のDISTINCTクエリとその下のクエリ(「構文糖」であると主張している)はどちらも重複する長さを削除します。ここでも同じことが当てはまります。OP では、クエリのように重複するCreationDatesではなく、重複するカテゴリを削除したいと考えています。それでも私を信じない場合は、自分でテストしてください。DISTINCT ON
インクリング

6

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

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

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


2

このコードを使用して、[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

あなたが望むものは何であれ、すべての明確な記録があります。


これらの中括弧[]は完全に混乱しています...これは有効なSQL構文ですか?
m13r 2014

1
角かっこはOrder、eventなどのキーワードをエスケープするためのものです。たとえば、テーブルに列が呼び出されているEvent場合、SQLが解析エラーをスローするのを停止する[Event]代わりに、次のEventように記述できます。
Ben Maxfield 2016年

1

2)CreationDateによる注文は非常に重要です

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

常にMAXを使い始めてGroup Byの重複を削除するのは非常に簡単です...根本的な質問を忘れるか無視してください...

OPは、MAXを使用すると最後に「作成」され、MINを使用すると最初に「作成」されることを理解していると考えられます...


3
これは実際には質問に答えているようには見えません。それは、質問への回答MAXとして独立したものではなく、他の回答者によるの使用に関するコメントのようです。
DaveyDaveDave 2018年

0
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

サブクエリによって、それはうまくいくはずです:

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

うーん…そうは思いません。外側の選択はソートされません。
Hossam El-Deen

これは機能しません。これが機能しないため、ここにいます
アミレザ

-1

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

SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC

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

SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC

12
これは実行されますが、OPが必要とするものは提供されません。OPは、CategoryとCreateDateの個別の組み合わせではなく、個別のカテゴリを必要としています。このコードは、同じCategoryの複数のインスタンスを生成する可能性があり、それぞれ異なるCreationDate値を持ちます。
MatBailie

-1

CTEを使用できます。

WITH DistinctMonitoringJob AS (
    SELECT DISTINCT Category Distinct_Category FROM MonitoringJob 
)

SELECT Distinct_Category 
FROM DistinctMonitoringJob 
ORDER BY Distinct_Category DESC

-3

次に試してみてください。ただし、大量のデータには役立ちません...

SELECT DISTINCT Cat FROM (
  SELECT Category as Cat FROM MonitoringJob ORDER BY CreationDate DESC
);

4
「TOPまたはFOR XMLも指定されていない限り、ビュー、インライン関数、派生テーブル、サブクエリ、および共通テーブル式では、ORDER BY句は無効です。」
TechplexEngineer 2013

orderByにCreationDate列を指定していないため、これは機能しません。
マウロビロッティ2014年

1
@TechplexEngineerコメントが正しくありません。ORDER BYサブクエリでの使用は完全に有効です。そして、誰かがあなたの間違ったコメントに賛成投票さえしました。
Racil Hilan 2014

私はこれを試していますが、@ TechplexEngineerで同じエラーが発生しています。ケース付きのカスタム注文を使用しています。
Ege Bayrak

-4

これは内部クエリを使用して行うことができます

$query = "SELECT * 
            FROM (SELECT Category  
                FROM currency_rates                 
                ORDER BY id DESC) as rows               
            GROUP BY currency";

-5
SELECT DISTINCT Category FROM MonitoringJob ORDER BY Category ASC

2
作成日でソートする必要があります!! それは非常に重要
RR

それで、注文したい列を自分で追加することは不可能ですか?例では、アルファベット順にエントリを示しました。作成日で注文する必要がある場合は、追加してください。それほど難しいことではありません。
フリケーン、2011年

8
-1:OPはそれを試みましたが、機能しませんでした。不可能であるため、OPを利用するときにその事実を無視したようです。重要な点は、DISTINCT演算子は、同じ作成日を持つ異なるカテゴリ値を持つ複数のレコードを照合することです。したがって、DISTINCTを使用する場合は、論理的に不可能です。これにより、必要なロジックがDISTINCTではなくGROUP BYにプッシュされ、作成日の集計(MAX)が可能になります。
MatBailie

実際、もしあなたがOPが何をしたかを詳しく見てみると、それは完全に不正なSQLです-私は単一の間違いを犯したのではなく、与えられた結果は彼が要求したものに対応します。私は-1に迷惑をかけません。人々を修正する前に、次に読むだけです。ありがとうございました。
フリケーン、2011年

8
「実際にはそれほど難しくはない」と言っても、CreationDateフィールドを直接追加することをお勧めします。これを行うと、不正なSQLが生成されます。OPをひいきにし、OPが最初に投稿したステートメントに戻るアドバイスを提供し、DISTINCTとDISTINCTにないフィールドによる順序付けの競合に気付かなかった場合、-1を獲得しました。さらに、「b」は「t」の前にあり、「1」は「4」の前にあります。したがって、OPによって与えられる結果は、アルファベット順ではありません。次に、あなた自身のアドバイスをお勧めします:次回(もっと注意深く)読んでください。
MatBailie
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.