将普通查询转换为子查询会产生不同的结果

Posted

技术标签:

【中文标题】将普通查询转换为子查询会产生不同的结果【英文标题】:convert normal query to subquery comes out with different results 【发布时间】:2019-11-06 09:59:44 【问题描述】:

我正在使用子查询(无JOIN)和普通(使用JOIN)查询做一个问题,但最后结果与这两个查询不同,我无法弄清楚这个问题。

问题是关于列出在这个平台至少预订过两次的狗主人的详细信息

PET_OWNER(Owner_id,Oname,OAdd),
PET(Pet_id,Pname,PType),
BOOKING(Booking_num,Pet_id)

每个主人可能有 >=1 只狗, 每只狗可能有 >=1 次预订

SELECT PET_OWNER.Owner_id,Oname,OAdd,COUNT(*) AS BOOKING
FROM PET_OWNER,
     PET,
     BOOKING 
WHERE PET_OWNER.Owner_id = PET.Owner_id
  AND PET.Pet_id = BOOKING.Pet_id
  AND PType = 'DOG'
GROUP BY PET_OWNER.Owner_id, Oname, OAdd
HAVING COUNT(*) >=2
ORDER BY PET_OWNER.Owner_id;`

这是正常查询,显示哪个狗主人至少预订了两次


SELECT *
FROM PET_OWNER
WHERE Owner_id IN ( SELECT Owner_id FROM PET
                    WHERE Pet_id IN ( SELECT Pet_id FROM BOOKING)
                      AND PType = 'DOG'
                    GROUP BY Owner_id 
                    HAVING COUNT(*) >1);

这个子查询的问题是,结果显示哪个主人至少有两只狗,但没有显示哪个狗主人至少预订了两次。 子查询已自动向我显示不同的 pet_id, 所以我不能指望预订表中的 Pet_id 因为它总是只显示 1 **此子查询中不允许任何连接

我应该在子查询代码中进行哪些更改? 我希望这两个查询有相同的结果

【问题讨论】:

为什么你使用子查询而不是连接??? .. 其中 IN 工作作为一个选择不同 JOIN 工作一个选择不不同 样本数据在这里真的很有帮助。 欢迎来到 SO。请看:Why should I provide an MCRE for what seems to me to be a very simple SQL query? mysql 还是 oracle?由于您没有收到不正确分组的错误,因此我假设 mysql.请不要标记未涉及的产品。 今日提示:使用现代、明确的JOIN 语法。更容易编写(没有错误),更容易阅读(和维护),如果需要更容易转换为外连接 【参考方案1】:

我认为您在子查询中需要group by,如下所示:

SELECT * FROM 
PET_OWNER 
WHERE Owner_id IN 
  ( SELECT Owner_id FROM PET
     WHERE Pet_id IN ( SELECT Pet_id FROM BOOKING 
     GROUP BY PET_ID HAVING COUNT(1) >1 ) AND PType = 'DOG';

干杯!!

【讨论】:

天啊,你真是太专业了!!【参考方案2】:

我认为您必须为此目的执行 2 个子查询:

SELECT * FROM PET_OWNER
 WHERE OWNER_Id IN (SELECT Owner_id FROM PET 
                     WHERE PType = 'DOG'
                       AND Pet_Id IN (SELECT Pet_id 
                                        FROM BOOKING
                                       GROUP BY Pet_id
                                       HAVING COUNT(*) > 1))
    OR OWNER_Id IN (SELECT Owner_id FROM PET 
                     WHERE PType = 'DOG'
                       AND Pet_Id IN (SELECT Pet_id 
                                        FROM BOOKING)
                     GROUP BY Pet_id
                     HAVING COUNT(*) > 1)

【讨论】:

【参考方案3】:

您可以通过joingroup by 获得至少两次预订的狗主人:

select p.owner_id
from booking b join
     pet p
     on p.pet_id = b.pet_id
where p.type = 'Dog'
group by p.owner_id
having count(*) >= 2;

您可以通过多种方式获取详细信息。一个简单的方法使用in

select o.*
from owner o
where o.owner_id in (select p.owner_id
                     from booking b join
                          pet p
                          on p.pet_id = b.pet_id
                     where p.type = 'Dog'
                     group by p.owner_id
                     having count(*) >= 2
                    );

【讨论】:

以上是关于将普通查询转换为子查询会产生不同的结果的主要内容,如果未能解决你的问题,请参考以下文章

Google Location API vs. Maps:为啥相同的查询会产生不同的结果?

具有 unnest 的 PostgreSQL 查询不返回空值的结果行

如果子查询的结果为 NULL,MySQL 整个查询将失败

将JOIN查询重写为子查询,缺少行?

SQL查询;如果子记录 = 条件则排除记录

如果子查询在 MySQL 中返回多于 1 行,如何将 JSON 放入列数据中