将结果限制为只有一个值只出现一次的行

问题描述:

我有一个比这里的示例更复杂的查询,但它只需返回某些字段在数据集中不会出现多次的行。将结果限制为只有一个值只出现一次的行

ACTIVITY_SK  STUDY_ACTIVITY_SK 
100    200 
101    201 
102    200 
100    203 

在这个例子中,我不想与100的ACTIVITY_SK任何记录返回,因为ACTIVITY_SK数据集中出现两次。

该数据是一个映射表,并在许多连接中使用,但是像这样的多个记录意味着数据质量问题,因此我需要将它们从结果中简单地删除,而不是在其他地方导致错误的连接。

SELECT 
    A.ACTIVITY_SK, 
    A.STATUS, 
    B.STUDY_ACTIVITY_SK, 
    B.NAME, 
    B.PROJECT 
FROM 
    ACTIVITY A, 
    PROJECT B 
WHERE 
    A.ACTIVITY_SK = B.STUDY_ACTIVITY_SK 

我试过这样的事情:

SELECT 
    A.ACTIVITY_SK, 
    A.STATUS, 
    B.STUDY_ACTIVITY_SK, 
    B.NAME, 
    B.PROJECT 
FROM 
    ACTIVITY A, 
    PROJECT B 
WHERE 
    A.ACTIVITY_SK = B.STUDY_ACTIVITY_SK 
WHERE A.ACTIVITY_SK NOT IN 
(

    SELECT 
    A.ACTIVITY_SK, 
    COUNT(*) 
    FROM 
     ACTIVITY A, 
     PROJECT B 
    WHERE 
    A.ACTIVITY_SK = B.STUDY_ACTIVITY_SK 
    GROUP BY A.ACTIVITY_SK 
    HAVING COUNT(*) > 1 

) 

但是,必须有这样做的更便宜的方式...

像这样的东西可能是一个有点“便宜”到运行:

SELECT 
    A.ACTIVITY_SK, 
    A.STATUS, 
    B.STUDY_ACTIVITY_SK, 
    B.NAME, 
    B.PROJECT 
PROJECT B INNER JOIN 
    (SELECT 
     ACTIVITY_SK, 
     MIN(STATUS) STATUS, 
    FROM 
     ACTIVITY 
    GROUP BY ACTIVITY_SK 
    HAVING COUNT(ACTIVITY_SK) = 1) A 
ON A.ACTIVITY_SK = B.STUDY_ACTIVITY_SK 
+0

您好,感谢......没想到我能做到的事情,我通过分组计数?看起来我无法避免两次有效地运行相同的查询,a和b之间的连接需要在两个查询中进行,因为这是创建重复项的连接。 – user1183688 2012-02-01 21:18:32

+0

你可以。通常我不使用COUNT(*),我总是尝试COUNT(PK_COLUMN),因为PK从来没有空值,优化器可以在该列上使用索引。 – Mithrandir 2012-02-01 21:22:16

另一种选择:

select * from (
    SELECT 
    A.ACTIVITY_SK, 
    A.STATUS, 
    B.STUDY_ACTIVITY_SK, 
    B.NAME, 
    B.PROJECT, 
    count(distinct a.pk) over (partition by a.activity_sk) AS c 
    FROM 
    ACTIVITY A, 
    PROJECT B 
    WHERE 
    A.ACTIVITY_SK = B.STUDY_ACTIVITY_SK 
) where c = 1; 

(其中a.pk是指从活动表中的唯一标识符)