我有两张桌子:
fccuser=# select count(*) from public.fine_collection where user_id = 5000;
count
-------
2500
(1 row)
fccuser=# select count(*) from public.police_notice where user_id = 5000;
count
-------
1011
(1 row)
当我发出
时fccuser=# select count(*)
from public.fine_collection, public.police_notice
where fine_collection.user_id = 5000
and fine_collection.user_id = police_notice.user_id;
我期待2500但我得到了
2527500 (1排)
,即两者的笛卡尔积。分析是:
fccuser=# explain analyze verbose select count(*) from public.fine_collection, public.police_notice where fine_collection.user_id = 5000 and fine_collection.user_id = police_notice.user_id;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=47657.20..47657.21 rows=1 width=0) (actual time=1991.552..1991.552 rows=1 loops=1)
Output: count(*)
-> Nested Loop (cost=0.86..39760.60 rows=3158640 width=0) (actual time=0.448..1462.155 rows=2527500 loops=1)
-> Index Only Scan using idx_user_id on public.fine_collection (cost=0.43..265.98 rows=8774 width=8) (actual time=0.213..2.448 rows=2500 loops=1)
Output: fine_collection.user_id
Index Cond: (fine_collection.user_id = 5000)
Heap Fetches: 1771
-> Materialize (cost=0.42..12.52 rows=360 width=2) (actual time=0.000..0.205 rows=1011 loops=2500)
Output: police_notice.user_id
-> Index Only Scan using idx_pn_userid on public.police_notice (cost=0.42..10.72 rows=360 width=2) (actual time=0.217..1.101 rows=1011 loops=1)
Output: police_notice.user_id
Index Cond: (police_notice.user_id = 5000)
Heap Fetches: 751
Planning time: 2.126 ms
Execution time: 1991.697 ms
(15 rows)
并且postgres文档说明当在非主要列上执行连接时,它首先创建笛卡尔积(交叉连接),然后应用过滤器。但我认为笛卡尔产品在我的情况下会包含所有具有相同user_id的行,因此不确定如何应用过滤器
左连接,内连接等也是如此,只有子查询似乎给出了2500的正确结果。
我有理由相信它在MySQL中不会以这种方式工作。有什么想法吗?
谢谢
答案 0 :(得分:0)
您的加入结果是正确的。您使用user_id
5000加入每个集合,并在每个警察通知中使用相同的user_id
。您有2500行和1011行连接在一起,这会产生2527500个新行。
答案 1 :(得分:0)
您正在使用旧版连接语法,因此这里的查询重新定义为使用可读的ANSI连接。
SELECT
count(*)
FROM public.fine_collection
INNER JOIN public.police_notice
ON (fine_collection.user_id = police_notice.user_id)
WHERE fine_collection.user_id = 5000;
所以,你正在做count(*)
。这会计算两个表的交叉积中与连接条件和where子句匹配的所有行。
换句话说,结果是每个表中user_id = 5000的行数,乘以。
您的查询与
完全相同SELECT
(SELECT count(*) FROM public.fine_collection WHERE user_id = 5000)
*
(SELECT count(*) FROM public.police_notice.user_id WHERE user_id = 5000);
是的,2500 * 1011 = 2527500,这样才完全正确。
如果您希望2500,则需要在fine_collection中加入或分组键。