Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何查找键重复但并非所有列都重复的行?_Sql_Tsql_Sql Server 2008 - Fatal编程技术网

Sql 如何查找键重复但并非所有列都重复的行?

Sql 如何查找键重复但并非所有列都重复的行?,sql,tsql,sql-server-2008,Sql,Tsql,Sql Server 2008,我正在使用一个表,它是一组其他表的摘录。根据键D1、D2和D3,提取表的所有行都应该是唯一的。事实并非如此。早期的开发人员似乎试图通过在从此表查询的所有列中使用SELECT DISTINCT来解决此问题。这将起作用,但仅当D1、D2、D3上重复的每一行也跨非键列重复时,忽略添加到提取表中的标识列 换句话说,给定行如下所示: D1 D2 D3 C4 C5 C6 === === === === === === A B C X1 X2 X3 A B C X1 X

我正在使用一个表,它是一组其他表的摘录。根据键D1、D2和D3,提取表的所有行都应该是唯一的。事实并非如此。早期的开发人员似乎试图通过在从此表查询的所有列中使用SELECT DISTINCT来解决此问题。这将起作用,但仅当D1、D2、D3上重复的每一行也跨非键列重复时,忽略添加到提取表中的标识列

换句话说,给定行如下所示:

D1  D2  D3  C4  C5  C6
=== === === === === ===
A   B   C   X1  X2  X3
A   B   C   X1  X2  X3
然后

将起作用,因为在D1、D2和D3上复制的行之间没有差异。但是如果表中包含

D1  D2  D3  C4  C5  C6
=== === === === === ===
A   B   C   X1  X2  X3
A   B   C   X1  X2  X4
然后,SELECT DISTINCT将为键A、B、C返回两行。此外,我们必须确定X3或X4中哪一个是正确的值

我知道如何找到D1,D2,D3上的副本。我甚至知道如何在除标识列以外的所有列中查找重复项:

;
WITH DUPLICATES(D1,D2,D3) AS
(
    SELECT D1, D2, D3
    FROM SOURCE
    GROUP BY D1, D2, D3
    HAVING COUNT(*)>1
)
SELECT S.D1, S.D2, S.D3, S.C4, S.C5, S.C6
FROM SOURCE S
INNER JOIN DUPLICATES D
    ON S.D1 = D.D1 AND S.D2 = D.D2 AND S.D3 = D.D3
ORDER BY S.D1, S.D2, S.D3, S.C4, S.C5, S.C6

问题是,我如何找到上述结果集的子集,这些结果集在D1、D2、D3上重复,但在D1、D2、D3、C4、C5、C6上不重复?

为什么不创建另一个表表达式来覆盖更多字段并连接到该字段

WITH DUPLICATEKEY(D1,D2,D3) AS
(
    SELECT D1, D2, D3
    FROM SOURCE
    GROUP BY D1, D2, D3
    HAVING COUNT(*)>1
)
WITH NODUPES(D1,D2,D3,C4,C5,C6) AS
(
SELECT 
S.D1, S.D2, S.D3, S.C4, S.C5, S.C6
FROM SOURCE S
GROUP BY
 S.D1, S.D2, S.D3, S.C4, S.C5, S.C6
HAVING COUNT(*)=1
)

SELECT S.D1, S.D2, S.D3, S.C4, S.C5, S.C6
FROM SOURCE S
INNER JOIN DUPLICATEKEY D
    ON S.D1 = D.D1 AND S.D2 = D.D2 AND S.D3 = D.D3

INNER JOIN NODUPES D2
    ON S.D1 = D2.D1 AND S.D2 = D2.D2 AND S.D3 = D2.D3

ORDER BY S.D1, S.D2, S.D3, S.C4, S.C5, S.C6

我还没有机会尝试康拉德的答案,但我自己想出了一个。这是一个相当无聊的时刻

因此,如果要查找集合A中除集合B中的行以外的所有行,请使用except运算符:

; 
WITH KEYDUPLICATES(D1,D2,D3) AS 
( 
    SELECT D1, D2, D3 
    FROM SOURCE 
    GROUP BY D1, D2, D3 
    HAVING COUNT(*)>1 
),
KEYDUPLICATEROWS AS
( 
    SELECT S.D1, S.D2, S.D3, S.C4, S.C5, S.C6 
    FROM SOURCE S 
    INNER JOIN KEYDUPLICATES D 
        ON S.D1 = D.D1 AND S.D2 = D.D2 AND S.D3 = D.D3 
),
FULLDUPLICATES AS
(
    SELECT S.D1, S.D2, S.D3, S.C4, S.C5, S.C6 
    FROM SOURCE S
    GROUP BY S.D1, S.D2, S.D3, S.C4, S.C5, S.C6 
    HAVING COUNT(*)>1
)
SELECT KR.D1, KR.D2, KR.D3, KR.C4, KR.C5, KR.C6
FROM KEYDUPLICATEROWS AS KR
EXCEPT
SELECT FD.D1, FD.D2, FD.D3, FD.C4, FD.C5, FD.C6
FROM FULLDUPLICATES AS FD
ORDER BY D1, D2, D3, C4, C5, C6
这似乎向我展示了1500行,它们在D1、D2、D3中是重复的,但它们仅在D1、D2、D3、C4、C5、C6的子集中是重复的。事实上,它们似乎在D1、D2、D3、C4、C5中都是重复的


如何确认这一点将是另一个问题。

这将有性能限制,但更容易理解:

SELECT D1, D2, D3
FROM TEST_KEY TK
WHERE (D1, D2, D3) IN
        (SELECT D1, D2, D3 FROM TEST_KEY TK2
         GROUP BY D1, D2, D3
         HAVING COUNT(*) > 1)
  AND (D1, D2, D3) IN
        (SELECT D1, D2, D3 FROM TEST_KEY TK2
         GROUP BY D1, D2, D3, C4, C5, C6
         HAVING COUNT(*) < 2)
无法在SQL Server上测试,希望语法良好

同样,不确定您在SQL Server中是否有分析功能,但此功能在Oracle中工作,可能更快:

WITH BAD_DUP AS (
SELECT TK.*,
       COUNT(1) OVER (PARTITION BY D1, D2, D3, C4, C5, C6 ORDER BY D1) FULL_DUP,
       COUNT(1) OVER (PARTITION BY D1, D2, D3 ORDER BY D1) KEY_DUP
FROM TEST_KEY TK)
SELECT * FROM BAD_DUP
WHERE FULL_DUP < KEY_DUP

想把它归结为一个查询……

你可以通过将表本身连接起来,说D都相等,至少有一个C不相等

CREATE TABLE #Source (
    D1 VARCHAR(2),
    D2 VARCHAR(2),
    D3 VARCHAR(2),
    C4 VARCHAR(2),
    C5 VARCHAR(2),
    C6 VARCHAR(2) );

INSERT INTO #Source VALUES ('A', 'B', 'C', 'X1', 'X2', 'X3');
INSERT INTO #Source VALUES ('A', 'B', 'C', 'X1', 'X2', 'X4');
INSERT INTO #Source VALUES ('A', 'B', 'D', 'X1', 'X2', 'X3');
INSERT INTO #Source VALUES ('A', 'B', 'D', 'X1', 'X2', 'X3');

SELECT S1.D1, S1.D2, S1.D3, S1.C4 C4_1, S2.C4 C4_2, S1.C5 C5_1, S2.C5 C5_2, S1.C6 C6_1, S2.C6 C6_2
FROM
    #Source S1
            INNER JOIN
    #Source S2
            ON
        (       S1.D1 = S2.D1 
            AND S1.D2 = S2.D2
            AND S1.D3 = S2.D3
            AND (   S1.C4 <> S2.C4
                 OR S1.C5 <> S2.C5
                 OR S1.C6 <> S2.C6
                 )
        );

DROP TABLE #Source;

还请注意,这与MS SQL 2000兼容,正如您稍后在中指出的,这是必需的。

我知道这是一个老问题,但我看到了关于这个问题的活动,我经常使用的技巧在这里没有作为答案呈现,而且非常简单,所以我想我会呈现它

SELECT D1, D2, D3, MIN(C4), MAX(C4), MIN(C5), MAX(C5), MIN(C6), MAX(C6)
FROM BAD_TABLE
GROUP BY D1, D2, D3
HAVING MIN(C4) <> MAX(C4)
    OR MIN(C5) <> MAX(C5)
    OR MIN(C6) <> MAX(C6)
这将显示关键帧上重复的所有关键帧,但非关键帧上存在差异,以及重复的差异范围


要查看其中的所有行,您需要将原始问题中的示例连接回BAD_表。

您能给出一个TL;版本博士?@WhatIs:如果我知道TL:DR的意思,我会的:-否决这个问题怎么了?如果你不说问题出在哪里,我该如何改进这个问题呢?StackOverflow正受到一小部分高声誉用户的损害,他们认为在没有仔细阅读的情况下进行向下投票是他们的权利。只有我的朋友了解一些事情。1投票否决时,人们不必发表评论,这与声誉无关,除了声誉。这不会改变。2如果在你发布问题将近一年后出现了否决票,那么问题可能是你没有接受答案。下面的答案没有一个有助于解决问题吗?你很接近,但我想看看哪些是关键重复项,而不是完全重复项。很抱歉,不知道这些词的正确名称。@John当然是对的。我在第二个CTE上更新了答案,对上面的代码进行了Count*=1A的小更正:D1、D2、D3、D4、C5、C6的最后一行顺序应为D1、D2、D3、C4、C5、C6,我无法发现它明确指出,如果具有相同键值的任何行组的某些非键列中存在差异,那么肯定只有一行与其他行不同,或者,例如,如果只有两行,则只有两行不同。真的是这样吗?我的意思是,是否会出现像bcx1y1z1、bcx1y1z1、bcx1y1z2、bcx1y1z2这样的情况,即四行只在最后一列的值上不同,两行包含Z1,另两行包含Z2?我的问题是,这种不一致性也应该考虑在内吗?谢谢。我会调查的。是的,我们有分析函数COUNT,ROW_COUNT,等等。重要的是能够按不同的分组进行划分,这样你只需要通过一次——我想有一种方法可以做到这一点,我只是不知道语法是否标准。我午餐时间的任务是尝试一下。我仍然在处理这些相同的查询,尽管我被允许在修复它们和TDD的同时进行单元测试。
D1   D2   D3   C4_1 C4_2 C5_1 C5_2 C6_1 C6_2
---- ---- ---- ---- ---- ---- ---- ---- ----
A    B    C    X1   X1   X2   X2   X4   X3
A    B    C    X1   X1   X2   X2   X3   X4
SELECT D1, D2, D3, MIN(C4), MAX(C4), MIN(C5), MAX(C5), MIN(C6), MAX(C6)
FROM BAD_TABLE
GROUP BY D1, D2, D3
HAVING MIN(C4) <> MAX(C4)
    OR MIN(C5) <> MAX(C5)
    OR MIN(C6) <> MAX(C6)