我有以下查询:
SELECT s.id, s.service_measure from service s, user_service_hist ush
WHERE s.id <> ush.service_id
我的 s 表格如下:
id | service_measure
--------------------
7 | a
8 | b
9 | c
我的 ush 表格如下:
id | service_id
--------------------
1 | 7
2 | 8
当我运行上述查询时,我希望并希望结果为
id | service_measure
--------------------
9 | c
相反,我的结果是:
id | service_measure
--------------------
8 | b
9 | c
7 | a
9 | c
看起来它正在运行查询2次。对于 ush 表的每一行一次。谁能告诉我为什么会这样?
答案 0 :(得分:3)
让我们分解您的查询:
SELECT s.id, s.service_measure
FROM service s, user_service_hist ush
WHERE s.id <> ush.service_id
首先,引擎通过使用from子句中的符号来进行交叉连接。
所以a,b,c连接到1,2导致
1. 7 a
2. 8 b
3. 9 c
4. 7 a
5. 8 b
6. 9 c
交叉连接将表中的每个记录连接到另一个表中的每个记录。这些非常慢,很少需要。想想你必须首先获取表1中的每条记录并将其与表2中的每条记录配对。连接只需匹配On like值否定生成交叉连接所做的笛卡尔的所有工作。 (我很少在我的工作中使用它们;通常在我需要生成测试数据时)
然后执行where子句,消除S.ID和ush.serivce_ID匹配的那些。
这消除了上面第1行和第5行,这就是为什么你只得到4条记录。
要获得预期结果,您需要使用不存在或外连接而不是交叉连接
SELECT s.id, s.service_measure
FROM service s
LEFT JOIN user_service_hist ush
on S.ID = USH.Service_ID
WHERE ush.Service_ID is null
或
SELECT s.id, s.service_measure
FROM service s
WHERE not exists (Select 1
from user_Service ush
where ush.Service_ID = s.ID)
或(因为您似乎正在学习联接)
SELECT s.id, s.service_measure
FROM user_service_hist ush
RIGHT JOIN service s
on S.ID = USH.Service_ID
WHERE ush.Service_ID is null
(注意我们在那里做的所有改变了连接的顺序和从左到右的单词)右连接说明包括右边表格中的所有记录,只包括左表中右边的那些记录。 (大多数人只是重新安排表格,所以他们都是左连接)
我认为如果ush表很小,in
会起作用,但由于表格不是设定的大小,因此对该表的记录增加会导致性能随着时间的推移而降低。不存在应该是具有适当索引的最有效的长期,尽管左连接提供了在需要时从ush表中获取额外数据的能力;但是对性能的轻微打击。
答案 1 :(得分:2)
你需要一个左排除连接!当您希望表 A 中所有元素 B 时,会发生左排除连接。 B 。看看图片!
SELECT
s.id, s.service_measure
FROM service s
LEFT JOIN user_service_hist ush
on ush.service_id = s.id
WHERE ush.service_id = NULL
答案 2 :(得分:1)
您的查询在service
和user_service_history
表之间执行笛卡尔积(这是from
部分的查询)。这个笛卡尔积的结果就是这个中间表:
s.id | s.service_measure | ush.id | ush.service_id
--------------------------------------------------
7 | a | 1 | 7
7 | a | 2 | 8
8 | b | 1 | 7
8 | b | 2 | 8
9 | c | 1 | 7
9 | c | 2 | 8
这个中间表然后被限制(where
子句)s.id <> ush.service_id
过滤掉了,这留下了:
s.id | s.service_measure | ush.id | ush.service_id
--------------------------------------------------
7 | a | 2 | 8
8 | b | 1 | 7
9 | c | 1 | 7
9 | c | 2 | 8
然后保留s.id
和service_measure
列,即可获得结果。
您想要的查询(来自我的头脑):
select s.id, s.service_measure
from service s
where s.id not in (
select ush.id
from user_service_history ush
)
答案 3 :(得分:0)
试试这个:
SELECT s.id, s.service_measure
FROM service s
LEFT JOIN user_service_hist ush ON s.id = ush.service_id
WHERE ush.service_id IS NULL