0

一个(我的简化版)查询如下所示:

SELECT id
FROM table
WHERE column1
IN
(
    SELECT column1
    FROM table
    GROUP BY column1
    HAVING COUNT(*) > 1
)

这将选择一个 id 列表,其中 column1 具有多个出现的值(换句话说,这些不是唯一的)。这可以按预期工作,但有一个例外:如果值 NULL 多次出现(这是可能的),则不选择任何 id。如果 NULL 被证明是非唯一的,那么选择列 ID 的正确方法是什么?

4

1 回答 1

2

使用EXISTS而不是IN: exists 更清晰(恕我直言),并且在大多数情况下它也更快。(IN (...)需要删除/抑制重复项和 NULL,因此:对集合进行排序)

在这种特殊情况下:聚合子查询只需要找出 group count() > 1。查询优化器可能没有意识到这一点,并在将它们与1.

SELECT tt.id
FROM thetable tt
WHERE EXISTS (
    SELECT * FROM thetable ex
    WHERE ex.column1 = tt.column1 AND ex.id <> tt.id
);

WRT 对 NULL 的抑制:如果其中一个或(或两者)碰巧为 NULL,则该WHERE ex.column1 = tt.column1子句将始终产生 false 。ex.column1tt.column1


更新。看来 OP 也想要带有 的元组column1 IS NULL,如果有更多的话。简单的解决方案是使用哨兵值(在 中不存在的值columnn1)并将其用作代理:(在下面的片段中-1用作代理值)

SELECT tt.id
FROM thetable tt
WHERE EXISTS (
    SELECT * FROM thetable ex
    WHERE COALESCE(ex.column1, -1) = COALESCE(tt.column1, -1)
    AND ex.id <> tt.id
);

另一种(显而易见的)方法是显式检查 NULL,但这需要一个OR子句和一堆括号,例如:

SELECT tt.id
FROM thetable tt
WHERE EXISTS (
    SELECT * FROM thetable ex
    WHERE (ex.column1 = tt.column1 
          OR (ex.column1 IS NULL AND tt.column1 IS NULL)
          )
    AND ex.id <> tt.id
);
于 2013-09-28T14:45:29.290 回答