使用 DISTINCT 显示独特的项目

Posted

技术标签:

【中文标题】使用 DISTINCT 显示独特的项目【英文标题】:Use DISTINCT to display unique items 【发布时间】:2021-12-01 11:39:39 【问题描述】:

我有 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 唯一的查询结果?

小提琴:https://www.db-fiddle.com/f/4D6VfqysPCWhQnh8zaFBps/2

【问题讨论】:

很高兴您提供了表定义、示例数据和查询。如果它们是可重现的(即没有明显的错误),那就太好了。 好的,这里是:db-fiddle.com/f/4D6VfqysPCWhQnh8zaFBps/2 OR 谓词的情况下,始终用括号对条件进行分组:1) 明确定义您想要AND 的内容。 2)不要依赖默认的评估顺序,避免意外结果。当您在 where 子句中使用外连接表的某些列时(is null 谓词除外),您将外连接转为内连接。 感谢您的建议。你能帮我解决这个问题吗? 说实话我是随机选择的。我不认为那个版本对这个问题很重要。 【参考方案1】:

您只需从表 active_pairs 中选择列即可。

在加入a.pair_id = b.id 之后,条件a.pair_id IS NULL 仅在表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小提琴here

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

...
ORDER BY pair, id;

还为到目前为止未排序的结果添加排序顺序。

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

对于大型active_pairs 表,可能有更快的解决方案,具体取决于未公开的信息,主要是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

【讨论】:

谢谢,pair_id 可以有多个值为“FR/EU”的记录。 pair VARCHAR(30), 不是唯一的。 对于几个重复项,DISTINCT ON 通常是最快的。 (无论如何它是最简单的。)请参阅:***.com/a/34715134/939860

以上是关于使用 DISTINCT 显示独特的项目的主要内容,如果未能解决你的问题,请参考以下文章

Spark 上的 SQL:如何获取 DISTINCT 的所有值?

R语言dplyr包对独特值(distinct)进行计数实战

pandas使用groupby函数和agg函数获取每个分组特定变量独特值的个数(number of distinct values in each group in dataframe)

在 2 个字段上应用 distinct 并获取每列的唯一数据

distinct是啥意思

Django Query distinct values 有效,但我无法使用查询结果