Bir sütunda DISTINCT SEÇİN


258

SQL Server kullanarak, var ...

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

İstiyorum

1   FOO-23  Orange
3   FOO-24  Apple

Bu sorgu beni oraya götürmüyor. DISTINCT'i yalnızca bir sütunda nasıl seçebilirim?

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

1
SKU sütunu verilerindeki soneki umursamadığınızı varsayabilir miyiz? IE, Sen sadece "FOO-" umurumda değil, "FOO-xx"
Kane

3
Diğer değerlere göre ID = 1, SKU = FOO-23'ü seçmenin mantığı nedir? ID = 1 için özel olarak cevap veren, ancak genel bir durum için başarısız olan bir sorgu oluşturmak kolaydır
gbn

4
gbn - bu aşırı basitleştirilmiş bir örnektir (açıkçası). Göstermeye çalıştığım şey her iki kriteri de karşılayan bir örnektir. Birinin seçildiği bir mantık yoktur (ve gerekmemektedir).
mmcglynn

Yanıtlar:


324

SQL Server 2005 veya daha üstündeyseniz, ROW_NUMBER () ile bir CTE kullanabilirsiniz:

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
Sorgunuzda CTE kullanmıyorsunuz . Bu sadece türetilmiş bir tablo. Ama burada bir CTE kullanmış olabilirsiniz .
Mark Byers

kehanet için "AS" yazmayın -> ... SKU 'FOO%' NEREDE)) NEREDE a.RowNumber = 1
Andre Nel

Bu bir CTE olmamasına rağmen (; CTE İLE ......) çalışır. içeride bölüm ile bir alt sorgu daha ....
user274294

Bu çeşitli yineleme gerçekten yararlı bir durum teşekkür ederim
ASLIM

42

En basit çözüm, sorgunuzla eşleşen minimum kimliği bulmak için bir alt sorgu kullanmak olacaktır. Aşağıdakiler GROUP BYyerine kullandığınız alt sorguda DISTINCT:

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

13

bunu dene:

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

DÜZENLEME
OP kez (şimdi tüm göstermiştir önce yalnızca BİR Sonuç satırını vardı) onun samle çıktı, bu doğru sorgu düzeltilmiş:

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
Bunu + 1'leyecektim, çünkü GROUP BY'ın doğru yol olduğunu düşünüyorum - ancak minimum kimlik ve minimum SKU aynı kayda ait olmayabilir. Belirli bir ÜRÜN için raporlanacak doğru ID ve SKU'nun ne olduğunu belirlemek zor.
Carl Manaster

8

6 yıl önce sorulduğunu biliyorum, ama bilgi hala bilgidir. SQL Server 2000 altında çalıştırmak zorunda olduğu gibi bu, yukarıdakilerden farklı bir çözümdür:

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

Burada, temel olarak diğer yanıtların bir çiftiyle aynı olan bir sürüm var, ancak bazı satır içi değerleri sayesinde test etmek için (ve istenmeyen tablolar oluşturmadan) yapıştırmayı SQL Server Management Studio'nuza kopyalayabilirsiniz.

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]
)

Sonuç

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

Aşağıdakileri görmezden geldim ...

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

yazarın hatalı kodunun sadece bir parçası ve sorunun bir parçası değil. Buraya bakan insanlara yardımcı olma olasılığı düşüktür.


-1

Bunu dene:

SELECT * FROM [TestData] WHERE Id IN(SELECT DISTINCT MIN(Id) FROM [TestData] GROUP BY Product)   

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.