SQL - 在同一个表中匹配相同的值,不同的列

Posted

技术标签:

【中文标题】SQL - 在同一个表中匹配相同的值,不同的列【英文标题】:SQL - Matching same value in same table, different columns 【发布时间】:2017-09-18 22:46:11 【问题描述】:

我正在尝试确认发送document_iddirection flag = 'O' 并接收相同document_id 并将其记录在同一个表中的进程,但在新行和不同列中:src_document_id,带有direction = 'I'。

需要识别已发送的记录,(方向标志 = O)没有与 src_document_id 匹配的值,其中 direction_flag = 'I'。当我检查出站值与入站值时,不确定我使用的是 EXISTS 还是 Not Exists。

下表中的 EX:查询应返回 Document_id 34567,因为它没有对应的 src_document_id,Direction_flag = I。

select
    document_id
from
    DOCUMENT_TABLE 
where
    direction_flag = 'O'
    and
    client_id = '9999'
    and
    EXISTS
    (
        select
            document_id
        from
            DOCUMENT_TABLE
        where
            document_id != src_document_id and direction_flag = 'I'
    )  

希望我说得够清楚了。不精通SQL。

DOCUMENT_ TABLE:

Document_id     client number   Direction flag    src_document_id 
12345             9999               O  
23456             9999               O
34567             9999               O  

aaaaa                                 I                12345
aaaab                                 I                23456

【问题讨论】:

【参考方案1】:

相关子查询的性能通常很差。我认为您的查询使用自联接子查询会更好。

(相关子查询一般来说是存在于SELECT 子句或WHERE 子句中的子查询,并针对集合中的每一行进行评估,这自然是低效的(想想:O(n*m) 复杂性)并且不'并不总是会产生优化的执行计划。)

我想要这个:

SELECT
    [source].document_id
FROM
    (
        SELECT
            document_id
        FROM
            document_table
        WHERE
            direction_flag = 'O'
    ) AS [source]
    LEFT JOIN
    (
        SELECT
            document_id,
            src_document_id
        FROM
            document_table
        WHERE
            direction_flag = 'I'
    ) AS [dest]
        ON [source].document_id = [dest].src_document_id
 WHERE
    dest.document_id IS NULL

请注意,我对子查询使用完整查询,因为与 @Donal gave in his answer 等更紧凑的查询相比,它使“document_table 用于源文档”和“document_table 用于目标文档”之间的意图和区别更加清晰- 这完全取决于样式和可读性,因为两个查询都是正确的。

【讨论】:

【参考方案2】:

您可以使用左连接在 id 字段上将表连接到自身。这将显示左侧的所有记录,仅显示右侧匹配的记录。在 where 子句中可以过滤掉不匹配的记录(src_document_id 为空)。

SELECT
d1.document_id
FROM DOCUMENT_TABLE d1
LEFT JOIN DOCUMENT_TABLE d2 ON d1.document_id = d2.src_document_id 
WHERE
d1.direction_flag = 'O' AND
d2.src_document_id IS NULL AND
d2.direction_flag = 'I'

【讨论】:

【参考方案3】:

Dai's answer 正确

但是Donal's answer 有一个小错误。正确答案应该是这样的:

SELECT
d1.document_id
FROM DOCUMENT_TABLE d1
LEFT JOIN DOCUMENT_TABLE d2 ON d1.document_id = d2.src_document_id 
AND d2.direction_flag = 'I'
WHERE
d1.direction_flag = 'O' AND
d2.src_document_id IS NULL

由于 "d2.src_document_id" 始终为 null,因此语句 "d2.direction_flag = 'I'" 在 where 条件下是无用的。

【讨论】:

以上是关于SQL - 在同一个表中匹配相同的值,不同的列的主要内容,如果未能解决你的问题,请参考以下文章

如何在具有相同 ID 的列中选择不同的值然后删除它们 PHP SQL Server

查询以匹配两个表中具有相同电话号码区号的列

在一个表中的不同行和不同列中查找相同的值SQL

SQL Query 从不同的表中选择相同的数据,显示所有记录,但显示/显示匹配

excel匹配相同ID不同对应数据?

SQL如何查询出某一列中不同值出现的次数?