SQL DISTINCT と TOP を同じクエリで使用する
この記事は、読者の一人である Nan が DISTINCT、TOP、および ORDER BY に関して最近送ってきた一連の質問からヒントを得たものです。 これらの無料ツールは、私のガイド「Getting Started Using SQL Server」を使って使い始めることができます。
How do the SQL Top and Distinct SELECT modifiers Work Together to Produce Results?
以下は Nan が最初に送ってきた質問です:
私は SELECT DISTINCT と SELECT について少し混乱しています。 たとえば、
SELECT DISTINCT TOP 10 FirstName,
LastName
FROM Person.Person
ORDER BY LastName
これは個別のファーストネームを見ているのでしょうか。 名前と姓の組み合わせが異なるのか?
What about
Select Distinct TOP 10 LastName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY LastName
I thought everyone would like to know the answer so I create a blog post.このような場合、どのように区別するのでしょうか。
DISTINCT と TOP – どっちが先?
最初のステートメントを見てみましょう。その目的は、姓と名の一意のリストを返すことです。
SELECT DISTINCT TOP 10 FirstName,
LastName
FROM Person.Person
ORDER BY LastName;
TOP 10 は順序付きセットから最初の 10 項目を返し、DISTINCT は重複をすべて削除します。
- テーブルはLastNameでソートされ、上位10項目が取得され、次に重複する名前が削除されますか。
- それとも重複が削除され、次に項目がソートされて上位10項目が表示されますか。
この質問に答える前に、DISTINCTはSELECT句のすべての列と式に対して動作するということを念頭に置いてください。
残念ながら、フィールドの1つのセットでDISTINCTを使用し、他のフィールドを表示する直接的な方法はありません。 SELECT ステートメントに列を追加すると、それらは DISTINCT 演算子の影響下に置かれるようになります。 直接と言うのは、DISTINCTリストを取得し、INNER JOINを使用して他の列を取り込むことができるからです。 DISTINCT に TOP 句を追加することは興味深いことです。
- Select DISTINCT Values from Table and order
- Select the TOP x rows from the results in step 1 and display.
If you try this yourself start with
SELECT FirstName,
LastName
FROM Person.Person
ORDER BY LastName
and notice the results.
AdventureWorks データベースでいくつかテストしてみたところ、処理の順序は以下のような感じであることが判明しました。 “Kim Ambercombie “を追跡してください。
![](https://www.essentialsql.com/wp-content/uploads/2015/05/OrderedResult.png)
Now run
SELECT DISTINCT FirstName,
LastName
FROM Person.Person
ORDER BY LastName
And you see that “Kim Ambercombine” is only one shown.
![](https://www.essentialsql.com/wp-content/uploads/2015/05/DistinctOrderedResults.png)
Then run
SELECT DISTINCT TOP 10 FirstName,
LastName
FROM Person.Person
ORDER BY LastName
And you see it returns first 10 unique first and last names as sorted by LastName.すると、ユニークな姓と名のリストが返されることがわかります。
![](https://www.essentialsql.com/wp-content/uploads/2015/05/OrderedResultDistinct10.png)
DISTINCT と TOP 10 操作、どちらが先に起こるか気になる場合は、最後の 2 つのクエリの結果を比較します。
“DISTINCT TOP 10” クエリは “DISTINCT” クエリの最初の 10 行を含むことに注意してください。
このことから、まずDISTINCTリストが作成され、次にTOP10の項目が返されることがわかります。
![](https://www.essentialsql.com/wp-content/uploads/2015/05/QueryPlan.png)
また、クエリープランを表示して確認することができます。 これを行うには、クエリを実行する前にメニューから [クエリ -> 実際のクエリ計画を含める] を選択します。
「Stream Aggregate」アイコンが DISTINCT 操作、「TOP」が TOP 10 操作です。
SELECT 文の中で DISTINCT が最初に表示されることは直感に反しますね。
DISTINCT and TOP with SELECT list Expressions
ナン氏の質問の 2 番目の部分は、式が DISTINCT 演算子でどのように扱われるかに関連しています。 FirstNameにLastNameを追加して作成します。
また、ORDER BYを使用する場合、Distinctを使用するとORDER BY項目が選択リストに表示されなければならないことに留意してください。 これを考えると、元の質問で提示されたステートメントを修正する必要があります:
SELECT DISTINCT FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY LastName
LastName が SELECT リストにないので実行できません。 はい、それは SELECT リスト内の式の一部ですが、それ自体では存在しません。 FullName で並べることは有効です。
以下の例では、この順序を使用します。
ステートメント
SELECT FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY FirstName + ' ' + LastName
は 19972 行を返します。 Distinct
SELECT DISTINCT FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY FirstName + ' ' + LastName
を追加すると、19516行が返されます。 最後にTop 10を追加すると、最初の10個の異なる名前の組み合わせを返します。
SELECT DISTINCT TOP 10 FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY FirstName + ' ' + LastName
これらのクエリをAdventureWorkデータベースで実行してみると、列だけを使用したときと同じ動作であることがわかります。