在一列上选择 DISTINCT
Posted
技术标签:
【中文标题】在一列上选择 DISTINCT【英文标题】:SELECT DISTINCT on one column 【发布时间】:2010-11-01 06:11:45 【问题描述】:使用 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
这个查询没有让我到达那里。如何仅在一列上 SELECT DISTINCT?
SELECT
[ID],[SKU],[PRODUCT]
FROM [TestData]
WHERE ([PRODUCT] =
(SELECT DISTINCT [PRODUCT] FROM [TestData] WHERE ([SKU] LIKE 'FOO-%'))
ORDER BY [ID]
【问题讨论】:
我们可以假设您不关心 SKU 列数据的后缀吗?即,您只关心“FOO-”而不关心“FOO-xx” 您选择 ID = 1、SKU = FOO-23 而不是其他值的逻辑是什么?创建一个专门针对 ID = 1 回答但在一般情况下失败的查询很容易 gbn - 这是一个过于简化的示例(显然)。我试图展示的是一个同时满足这两个标准的例子。没有(也不需要)选择一个逻辑。 【参考方案1】:这是一个版本,与其他几个答案基本相同,但由于一些内联值,您可以将粘贴复制到 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-%')
作为作者错误代码的唯一部分,而不是问题的一部分。这对看这里的人不太可能有帮助。
【讨论】:
开发工作和测试的好主意,无需创建测试表。谢谢。【参考方案2】:试试这个:
SELECT * FROM [TestData] WHERE Id IN(SELECT DISTINCT MIN(Id) FROM [TestData] GROUP BY Product)
【讨论】:
【参考方案3】:我知道 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
【讨论】:
【参考方案4】:最简单的解决方案是使用子查询来查找与您的查询匹配的最小 ID。在子查询中使用GROUP BY
而不是DISTINCT
:
SELECT * FROM [TestData] WHERE [ID] IN (
SELECT MIN([ID]) FROM [TestData]
WHERE [SKU] LIKE 'FOO-%'
GROUP BY [PRODUCT]
)
【讨论】:
【参考方案5】:试试这个:
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 更正了他的示例输出(以前只有一个结果行,现在已全部显示),这就是正确的查询:
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
【讨论】:
【参考方案6】: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'
【讨论】:
本来要为此 +1,因为我认为 GROUP BY 是正确的方法 - 但最小 ID 和最小 SKU 可能不恰好属于同一记录。很难确定要为给定产品报告的正确 ID 和 SKU 是什么。【参考方案7】:假设您使用的是 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
【讨论】:
您没有在查询中使用CTE。那只是一个派生表。但你是对的,你可以在这里使用 CTE。 为 oracle 省略 "AS" -> ...WHERE SKU LIKE 'FOO%') a WHERE a.RowNumber = 1 虽然它不是 CTE (;WITH CTE ......),但它仍然有效。更多的是内部分区的子查询.... 这在任何各种重复中都非常有用,谢谢以上是关于在一列上选择 DISTINCT的主要内容,如果未能解决你的问题,请参考以下文章
在一列上选择 DISTINCT,返回多个其他列(SQL Server)