使用 DISTINCT 显示唯一项

Use DISTINCT to display unique items

我有 2 个表,我想查询和显示数据差异:

CREATE TABLE order_splits_config (
    id                   INT,
    pair_id              INT
);

CREATE TABLE active_pairs (
    id                  INT,
    pair                VARCHAR(30),
    exchange_active     boolean,
    exchange_id         INT
);

INSERT INTO order_splits_config(id, pair_id)
VALUES (1, 83);
INSERT INTO order_splits_config(id, pair_id)
VALUES (2, 58);
INSERT INTO order_splits_config(id, pair_id)
VALUES (34, 34);

INSERT INTO active_pairs(id, pair, exchange_active, exchange_id)
VALUES (1, 'US/EN', true, 2);
INSERT INTO active_pairs(id, pair, exchange_active, exchange_id)
VALUES (2, 'GB/UK', true, 3);
INSERT INTO active_pairs(id, pair, exchange_active, exchange_id)
VALUES (2, 'FR/EU', true, 4);

我用这个查询来查询差异:

SELECT b.id, b.pair, b.exchange_id
FROM order_splits_config a
FULL OUTER JOIN active_pairs b
ON a.pair_id = b.id
WHERE a.pair_id IS NULL
OR b.id IS NULL
AND b.exchange_active = 'true';

这会打印很多行,例如(数据只是为了举例):

#,pair,id,exchange_id
1, US/EN,332,1
2, GB/UK,112,1
3, GB/UK,113,1
4, FR/EU,221,5
5, FR/EU,183,2
...

如何使用 DISTINCT 才能从 pair 唯一的查询中获得结果?

FIDDLE: https://www.db-fiddle.com/f/4D6VfqysPCWhQnh8zaFBps/2

您只有 select 列从 table active_pairs 开始。

加入 a.pair_id = b.id 后,条件 a.pair_id IS NULL 仅当 table order_splits_config AS a 中没有匹配行时才为真,更有效的表述为 NOT EXISTS 而不是 FULL JOIN.

至于 b.id IS NULL AND b.exchange_active = 'true':同样,b.id 只能是 NULL 对于 a 的行,其中没有找到匹配的 b - 在这种情况下b.exchange_active 永远不可能是真的。因此,该子句有效地消除了 a 中刚刚由 FULL JOIN 添加的所有行,这些行将在结果中显示为所有 NULL 值,因为只有 b 中的列。简而言之:不要FULL JOIN开始。

如果active_pairs.pair定义为UNIQUE,归结为:

SELECT id, pair, exchange_id
FROM   active_pairs b
WHERE  NOT EXISTS (SELECT FROM order_splits_config a WHERE a.pair_id = b.id);

如果 active_pairs.pair 未定义 UNIQUE,简单的解决方案是 DISTINCT ON:

SELECT DISTINCT ON (pair)
       id, pair, exchange_id
FROM   active_pairs b
WHERE  NOT EXISTS (SELECT FROM order_splits_config a WHERE a.pair_id = b.id);

db<>fiddle here

pair 的每组重复中,你会得到一个 任意 的选择。
对于 确定性 选择,定义要选择的内容并相应地添加 ORDER BY 子句。示例:要获得最小的 id,请添加:

...
ORDER BY pair, id;

还为迄今为止未排序的结果添加排序顺序。

如果 order_splits_config 不是非常小,请在 (pair_id) 上建立索引以加快速度。

可能有 muchactive_pairs table 更快的解决方案,具体取决于未公开的信息,主要是列 pair 的基数(有多少重复值)。

参见:

  • Select first row in each GROUP BY group?
  • Select rows which are not present in other table
  • Optimize GROUP BY query to retrieve latest row per user