从SQL查询中删除重复项(不仅仅是“使用不同”)

时间:2011-02-03 21:00:29

标签: sql duplicates distinct

这可能很简单,这是我的查询:

SELECT DISTINCT U.NAME, P.PIC_ID
FROM USERS U, PICTURES P, POSTINGS P1
WHERE U.EMAIL_ID = P1.EMAIL_ID AND P1.PIC_ID = P.PIC_ID AND P.CAPTION LIKE '%car%';

但这只会删除重复行,其中行具有相同的u.name和p.pic_id。我想要它,如果有任何重复的名称,它只是遗漏了其他行。这是一个奇怪的查询,但一般来说,如何将distinct应用于SELECT子句的单个列?

5 个答案:

答案 0 :(得分:18)

任意选择保持最小PIC_ID。另外,请避免使用隐式连接语法。

SELECT U.NAME, MIN(P.PIC_ID)
    FROM USERS U
        INNER JOIN POSTINGS P1
            ON U.EMAIL_ID = P1.EMAIL_ID
        INNER JOIN PICTURES P
            ON P1.PIC_ID = P.PIC_ID
    WHERE P.CAPTION LIKE '%car%'
    GROUP BY U.NAME;

答案 1 :(得分:2)

你的问题有点令人困惑;你想每个用户只显示一行,或者你想在每张图片中显示一行但是在U.NAME字段中抑制重复值?我想你想要第二个;如果不是第一个有很多答案。

是否显示重复值是显示逻辑,而SQL实际上并不是这样设计的。您可以在循环中使用游标来逐行处理结果,但是会丢失很多性能。如果你有一个像.NET语言或Java这样的“智能”前端语言,那么无论你将这些数据放入哪种结构中,都可以通过廉价操作来抑制重复值,然后再在UI中显示它。

如果您正在使用Microsoft SQL Server,并且要在数据层完成转换HAS,您可以考虑使用CTE(计算表表达式)来保存初始查询,然后从CTE的每一行中选择值根据前一行中的列是否包含相同的数据。它会比光标更高效,但无论如何它都会有点混乱。观察:

USING CTE (Row, Name, PicID)
AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY U.NAME, P.PIC_ID),
       U.NAME, P.PIC_ID
    FROM USERS U
        INNER JOIN POSTINGS P1
            ON U.EMAIL_ID = P1.EMAIL_ID
        INNER JOIN PICTURES P
            ON P1.PIC_ID = P.PIC_ID
    WHERE P.CAPTION LIKE '%car%'
    ORDER BY U.NAME, P.PIC_ID 
)
SELECT
    CASE WHEN current.Name == previous.Name THEN '' ELSE current.Name END,
    current.PicID
FROM CTE current
LEFT OUTER JOIN CTE previous
   ON current.Row = previous.Row + 1
ORDER BY current.Row

以上示例是TSQL特定的;它不能保证在PL / SQL等任何其他DBPL中工作,但我认为大多数企业级SQL引擎都有类似的东西。

答案 2 :(得分:1)

您需要告诉查询要为其他列选择哪个值,MINMAX似乎是合适的选择。

 SELECT
   U.NAME, MIN(P.PIC_ID)
 FROM
   USERS U,
   PICTURES P,
   POSTINGS P1
 WHERE
   U.EMAIL_ID = P1.EMAIL_ID AND
   P1.PIC_ID = P.PIC_ID AND
   P.CAPTION LIKE '%car%'
 GROUP BY
   U.NAME;

答案 3 :(得分:1)

如果我理解正确,您希望列出仅在一列上排除重复,内部联接到子选择

select u.* [whatever joined values]
from users u
inner join
(select name from users group by name having count(*)=1) uniquenames
on uniquenames.name = u.name

答案 4 :(得分:0)

如果我理解正确,您需要具有相同名称(及其不同ID)的所有图片的列表,以使其名称在表格中出现多次。我认为这样做可以解决问题:

SELECT U.NAME, P.PIC_ID
FROM USERS U, PICTURES P, POSTINGS P1
WHERE U.EMAIL_ID = P1.EMAIL_ID AND P1.PIC_ID = P.PIC_ID AND U.Name IN (
SELECT U.Name 
FROM USERS U, PICTURES P, POSTINGS P1
WHERE U.EMAIL_ID = P1.EMAIL_ID AND P1.PIC_ID = P.PIC_ID AND P.CAPTION LIKE '%car%';
GROUP BY U.Name HAVING COUNT(U.Name) > 1)

我没有执行它,因此可能存在语法错误或两个语法错误。