1つの列に対するSELECT DISTINCT


258

SQL Serverを使用して、私は...

ID  SKU     PRODUCT
=======================
1   FOO-23  Orange
2   BAR-23  Orange
3   FOO-24  Apple
4   FOO-25  Orange

が欲しいです

1   FOO-23  Orange
3   FOO-24  Apple

このクエリは私をそこに導きません。1つの列のみでDISTINCTを選択するにはどうすればよいですか?

SELECT 
[ID],[SKU],[PRODUCT]
FROM [TestData] 
WHERE ([PRODUCT] = 
(SELECT DISTINCT [PRODUCT] FROM [TestData] WHERE ([SKU] LIKE 'FOO-%')) 
ORDER BY [ID]

1
SKU列データのサフィックスについて気にしないと想定できますか?IE、あなたは「FOO-」だけを気にし、「FOO-xx」は気にしない
ケイン

3
他の値よりもID = 1、SKU = FOO-23を選択するためのロジックは何ですか?ID = 1で特定の応答をするクエリを作成するのは簡単ですが、一般的なケースでは失敗します
gbn

4
gbn-これは過度に単純化された例です(明らかに)。私が見せようとしているのは、両方の基準を満たす1つの例です。選択されるロジックはありません(その必要はありません)。
mmcglynn 2009年

回答:


323

SQL Server 2005以降を使用している場合は、ROW_NUMBER()でCTEを使用できます。

SELECT  *
FROM    (SELECT ID, SKU, Product,
                ROW_NUMBER() OVER (PARTITION BY PRODUCT ORDER BY ID) AS RowNumber
         FROM   MyTable
         WHERE  SKU LIKE 'FOO%') AS a
WHERE   a.RowNumber = 1

37
クエリでCTEを使用していません。これは単なる派生テーブルです。しかし、ここではCTEを使用できたはずです。
Mark Byers、2011

Oracleの場合は「AS」を省略-> ... WHERE SKU LIKE 'FOO%')a WHERE a.RowNumber = 1
Andre Nel

CTEではありませんが、これは機能します(; WITH CTE ......)。内部によるパーティションの
サブクエリの詳細

これは、さまざまな複製で本当に役立つケースです。ありがとう
ASLIM

42

最も簡単な解決策は、クエリに一致する最小IDを見つけるためにサブクエリを使用することです。GROUP BY代わりに使用するサブクエリでDISTINCT

SELECT * FROM [TestData] WHERE [ID] IN (
   SELECT MIN([ID]) FROM [TestData]
   WHERE [SKU] LIKE 'FOO-%'
   GROUP BY [PRODUCT]
)

13

これを試して:

SELECT 
    t.*
    FROM TestData t
        INNER JOIN (SELECT
                        MIN(ID) as MinID
                        FROM TestData
                        WHERE SKU LIKE 'FOO-%'
                   ) dt ON t.ID=dt.MinID

EDIT
OPは彼samle出力が(以前は1つの結果行を持っていた、今すべてが示されている)修正後は、これは正しいクエリです:

declare @TestData table (ID int, sku char(6), product varchar(15))
insert into @TestData values (1 ,  'FOO-23'      ,'Orange')
insert into @TestData values (2 ,  'BAR-23'      ,'Orange')
insert into @TestData values (3 ,  'FOO-24'      ,'Apple')
insert into @TestData values (4 ,  'FOO-25'      ,'Orange')

--basically the same as @Aaron Alton's answer:
SELECT
    dt.ID, dt.SKU, dt.Product
    FROM (SELECT
              ID, SKU, Product, ROW_NUMBER() OVER (PARTITION BY PRODUCT ORDER BY ID) AS RowID
              FROM @TestData
              WHERE  SKU LIKE 'FOO-%'
         ) AS dt
    WHERE dt.RowID=1
    ORDER BY dt.ID

8
SELECT min (id) AS 'ID', min(sku) AS 'SKU', Product
    FROM TestData
    WHERE sku LIKE 'FOO%' -- If you want only the sku that matchs with FOO%
    GROUP BY product 
    ORDER BY 'ID'

3
GROUP BYが正しい方法だと思うので、これを+1していましたが、最小IDと最小SKUが同じレコードに属していない場合があります。特定の製品について報告する正しいIDとSKUを特定するのは困難です。
カールマナスター2009年

8

6年以上前に尋ねられたことは知っていますが、知識はまだ知識です。これは、SQL Server 2000で実行する必要があったため、上記のすべてとは異なるソリューションです。

DECLARE @TestData TABLE([ID] int, [SKU] char(6), [Product] varchar(15))
INSERT INTO @TestData values (1 ,'FOO-23', 'Orange')
INSERT INTO @TestData values (2 ,'BAR-23', 'Orange')
INSERT INTO @TestData values (3 ,'FOO-24', 'Apple')
INSERT INTO @TestData values (4 ,'FOO-25', 'Orange')

SELECT DISTINCT  [ID] = ( SELECT TOP 1 [ID]  FROM @TestData Y WHERE Y.[Product] = X.[Product])
                ,[SKU]= ( SELECT TOP 1 [SKU] FROM @TestData Y WHERE Y.[Product] = X.[Product])
                ,[PRODUCT] 
            FROM @TestData X  

0

これは、基本的に他のいくつかの回答と同じバージョンですが、インライン値のおかげで、SQL Server Management Studioにコピーして貼り付け、(不要なテーブルを生成せずに)テストできます。

WITH [TestData]([ID],[SKU],[PRODUCT]) AS
(
    SELECT *
    FROM (
        VALUES
        (1,   'FOO-23',  'Orange'),
        (2,   'BAR-23',  'Orange'),
        (3,   'FOO-24',  'Apple'),
        (4,   'FOO-25',  'Orange')
    )
    AS [TestData]([ID],[SKU],[PRODUCT])
)

SELECT * FROM [TestData] WHERE [ID] IN 
(
    SELECT MIN([ID]) 
    FROM [TestData] 
    GROUP BY [PRODUCT]
)

結果

ID  SKU     PRODUCT
1   FOO-23  Orange
3   FOO-24  Apple

私は以下を無視しました...

WHERE ([SKU] LIKE 'FOO-%')

作者の不完全なコードの唯一の部分であり、質問の一部ではありません。ここを見る人に役立つとは思えない。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.