【问题标题】:SQL Query JOIN on the same table for a given dataSQL 查询 JOIN 对给定数据的同一张表
【发布时间】:2018-05-09 05:01:30
【问题描述】:

我有以下表格和数据:

CREATE TABLE TEST_TABLE (
  ID NUMBER(6) NOT NULL,
  COMMON_SEQ NUMBER(22),
  NAME VARCHAR(20),
  CONSTRAINT PK_CONST PRIMARY KEY (ID)
);
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1001, NULL, 'Michelle');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1002, NULL, 'Tiberius');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1003, NULL, 'Marigold');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1004, 999, 'Richmond');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1005, 999, 'Marianne');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1006, NULL, 'Valentin');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1007, 888, 'Juliette');
INSERT INTO TEST_TABLE (ID, COMMON_SEQ, NAME) VALUES (1008, NULL, 'Lawrence');

此表中的某些记录通过 COMMON_SEQ 的公共值相互关联(例如,999 的 COMMON_SEQ 与 Richmond 和 Marianne 相关)。

如何根据给定 ID 选择所有名称作为输入?

我尝试将表连接到自身(当 COMMON_SEQ 为空时可以正常工作)。此示例返回 Michelle 记录:

SELECT T.ID, T.COMMON_SEQ,T.NAME
FROM TEST_TABLE T 
LEFT JOIN TEST_TABLE T2 ON NOT T.COMMON_SEQ is NULL 
  AND T.COMMON_SEQ=T2.COMMON_SEQ AND T.ID<>T2.ID
WHERE T.ID=1001

但它不会返回 ID 1004 的 2 条记录。此示例仅返回 Richmond 记录(但我还需要返回 Marianne 记录):

SELECT T.ID, T.COMMON_SEQ,T.NAME
FROM TEST_TABLE T 
LEFT JOIN TEST_TABLE T2 ON NOT T.COMMON_SEQ is NULL 
  AND T.COMMON_SEQ=T2.COMMON_SEQ AND T.ID<>T2.ID
WHERE T.ID=1004

当我只提供一个 ID 值(1004 或 1005)时,如何改进/重写查询以返回 Richmond 和 Marianne 记录?

【问题讨论】:

  • 因为NULL = NULL 不正确。 (如果有的话,你可以使用x IS NOT DISTINCT FROM y
  • 您使用的是哪个数据库?甲骨文?
  • @Ramesh 我使用 2 个数据库:H2 和 Oracle。我需要对它们都适用的通用 SQL。

标签: sql oracle join h2


【解决方案1】:

你可以使用:

SELECT *
FROM TEST_TABLE t
WHERE COMMON_SEQ IN (SELECT COMMON_SEQ
                     FROM TEST_TABLE t1
                     WHERE t1.ID = 1004)
  OR t.ID = 1004;                  

DBFiddle Demo

两次传递相同的参数来处理COMMON_SEQ中的NULL

【讨论】:

  • 谢谢!我刚刚尝试过,它返回了我所有测试用例的预期结果!
  • @user1697575 很高兴听到这个消息。
【解决方案2】:

试试这个

 SELECT COALESCE (ty.id, tx.id) AS id,
        COALESCE (ty.common_seq, tx.common_seq) AS common_seq,
        COALESCE (ty.name, tx.name) AS name
  FROM test_table tx LEFT OUTER JOIN test_table ty
             ON (tx.common_seq = ty.common_seq)
 WHERE tx.ID = 1004;

这样,您可以避免使用 IN 或 EXISTS,这可能会提高性能。

【讨论】:

  • @user1697575 - 很高兴为您提供帮助
  • 只是好奇你为什么使用 COALESCE 功能?我不能只使用 SELECT ty.* FROM ... 吗?
  • 为什么左连接“可能比半连接更高效”(IN 或 EXISTS 条件)?我问的原因是,至少在 Oracle 中,情况正好相反(原因很明显:半联接比联接要做的工作更少)。
  • @user1697575 - ty.* 仅适用于具有 common_seq 的 ID。例如,如果您尝试 id = 1001,您将获得 NULL 记录。
猜你喜欢
  • 2014-05-08
  • 1970-01-01
  • 1970-01-01
  • 2020-04-10
  • 2021-09-17
  • 1970-01-01
  • 1970-01-01
  • 2020-03-08
  • 1970-01-01
相关资源
最近更新 更多