使用 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 的所有值?
pandas使用groupby函数和agg函数获取每个分组特定变量独特值的个数(number of distinct values in each group in dataframe)