เลือก 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

แบบสอบถามนี้ไม่ได้รับฉันไปที่นั่น ฉันจะเลือก 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"
Kane

3
ตรรกะของคุณในการเลือก ID = 1, SKU = FOO-23 เหนือค่าอื่น ๆ คืออะไร มันง่ายที่จะสร้างแบบสอบถามที่ตอบ specfically สำหรับ ID = 1 แต่ล้มเหลวสำหรับกรณีทั่วไป
GBN

4
gbn - นี่เป็นตัวอย่างที่ง่ายเกินไป (ชัด) สิ่งที่ฉันพยายามแสดงคือตัวอย่างหนึ่งที่เป็นไปตามเกณฑ์ทั้งสอง ไม่มีตรรกะ (และไม่จำเป็น) ตรรกะที่เลือก
mmcglynn

คำตอบ:


323

สมมติว่าคุณใช้ SQL Server 2005 ขึ้นไปคุณสามารถใช้ CTE กับ 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

37
คุณไม่ได้ใช้CTEในการสืบค้นของคุณ นั่นเป็นเพียงตารางที่ได้รับมา แต่คุณพูดถูกที่คุณสามารถใช้ CTE ได้ที่นี่
Mark Byers

ปล่อย "AS" สำหรับ oracle -> ... WHERE SKU ต้องการ 'FOO%') a WHERE a.RowNumber = 1
Andre Nel

วิธีนี้ใช้ได้แม้ว่าจะไม่ใช่ CTE (; กับ 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

แก้ไข
เมื่อ OP แก้ไขผลลัพธ์ samle ของเขา (ก่อนหน้านี้มีแถวผลลัพธ์เพียงแถวเดียวตอนนี้แสดงทั้งหมด) นี่คือแบบสอบถามที่ถูกต้อง:

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
จะ +1 สิ่งนี้เพราะฉันคิดว่า GROUP BY เป็นวิธีที่ถูกต้อง แต่รหัสขั้นต่ำและ SKU ขั้นต่ำอาจไม่เกิดขึ้นกับระเบียนเดียวกัน ยากที่จะระบุว่า ID และ SKU ที่ถูกต้องคืออะไรเพื่อรายงานสำหรับผลิตภัณฑ์ที่ระบุ
Carl Manaster

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.