带有“<>”的MySQL SELECT查询运算符给出了奇怪的结果

时间:2016-11-07 19:34:10

标签: mysql sql

我有以下查询:

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 表的每一行一次。谁能告诉我为什么会这样?

4 个答案:

答案 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

SQL Joins

答案 2 :(得分:1)

您的查询在serviceuser_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.idservice_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