PILIH berbeda di satu kolom

258

Menggunakan SQL Server, saya punya ...

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

saya ingin

1   FOO-23  Orange
3   FOO-24  Apple

Kueri ini tidak membuat saya di sana. Bagaimana saya bisa MEMILIH PERBEDAAN hanya pada satu kolom?

SELECT 
[ID],[SKU],[PRODUCT]
FROM [TestData] 
WHERE ([PRODUCT] = 
(SELECT DISTINCT [PRODUCT] FROM [TestData] WHERE ([SKU] LIKE 'FOO-%')) 
ORDER BY [ID]
mmcglynn
sumber
1
Bisakah kami berasumsi bahwa Anda tidak peduli dengan akhiran pada data kolom SKU? IE, Anda hanya peduli tentang "FOO-" dan bukan "FOO-xx"
Kane
3
Apa logika Anda untuk memilih ID = 1, SKU = FOO-23 di atas nilai lainnya? Sangat mudah untuk membuat query yang jawaban specfically untuk ID = 1 tetapi gagal untuk kasus umum
GBN
4
gbn - ini adalah contoh yang terlalu disederhanakan (jelas). Apa yang saya coba tunjukkan adalah salah satu contoh yang memenuhi kedua kriteria. Tidak ada (dan tidak perlu) logika yang dipilih.
mmcglynn

Jawaban:

323

Dengan asumsi Anda menggunakan SQL Server 2005 atau lebih tinggi, Anda dapat menggunakan CTE dengan ROW_NUMBER ():

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
Aaron Alton
sumber
37
Anda tidak menggunakan CTE dalam permintaan Anda. Itu hanya tabel turunan. Tapi Anda benar bahwa Anda bisa menggunakan CTE di sini.
Mark Byers
tinggalkan "AS" untuk oracle -> ... WHERE SKU LIKE 'FOO%') a WHERE a.RowNumber = 1
Andre Nel
Ini berfungsi meskipun itu bukan CTE (; DENGAN CTE ......). lebih dari satu permintaan dengan partisi di dalam ....
user274294
ini adalah kasus yang sangat berguna dalam berbagai duplikasi, terima kasih
ASLIM
42

Solusi paling sederhana adalah dengan menggunakan subquery untuk menemukan ID minimum yang cocok dengan kueri Anda. Di subquery yang Anda gunakan GROUP BYbukan DISTINCT:

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

coba ini:

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
setelah OP mengoreksi output samle-nya (sebelumnya hanya memiliki SATU baris hasil, sekarang semuanya ditampilkan), ini adalah permintaan yang benar:

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
KM.
sumber
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'

sumber
3
Akan memberi ini +1, karena saya pikir GROUP BY adalah cara yang tepat - tetapi ID minimum dan SKU minimum mungkin bukan milik catatan yang sama. Sulit untuk menentukan ID dan SKU mana yang harus dilaporkan untuk PRODUCT yang diberikan.
Carl Manaster
8

Saya tahu itu ditanyakan lebih dari 6 tahun yang lalu, tetapi pengetahuan masih pengetahuan. Ini adalah solusi yang berbeda dari semua di atas, karena saya harus menjalankannya di bawah 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  
Bartosz X
sumber
0

Berikut ini adalah versi, pada dasarnya sama dengan beberapa jawaban lainnya, tetapi Anda dapat menyalin paste ke SQL Server Management Studio Anda untuk menguji, (dan tanpa menghasilkan tabel yang tidak diinginkan), berkat beberapa nilai inline.

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

Hasil

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

Saya telah mengabaikan yang berikut ...

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

sebagai satu-satunya bagian dari kode yang salah penulis dan bukan bagian dari pertanyaan. Tidak mungkin membantu orang yang mencari di sini.

Ivan
sumber
-1

Coba ini:

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

Anna Karthi
sumber