论坛首页 综合技术论坛

关于简单的SQL子查询改写成联合查询

浏览 5295 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-16  
需求是在“雇员通信录”表里插入订单数超过100的员工信息。

子查询写法:
SELECT 雇员ID,姓氏,名字,邮政编码,城市,地址,家庭电话 FROM 雇员
WHERE 雇员ID IN
(
   SELECT 雇员ID FROM 订单
    GROUP BY 雇员ID
   HAVING COUNT(订单ID) > 100
)

改写成联合查询为:
SELECT
雇员.雇员ID,雇员.姓氏,雇员.名字,雇员.邮政编码,雇员.城市,雇员.地址,雇员.家庭电话
COUNT(订单.订单ID)
FROM 雇员
INNER JOIN 订单
ON 雇员.ID = 订单.雇员ID
GROUP BY  订单.雇员ID HAVING COUNT(订单ID) > 100

提问如下:
1.子查询和联合查询的区别有几点?
2.子查询改写成联合查询后的SQL语句是否错误?
3.在实际的操作过程中,我们如何写健壮的SQL语句?
   发表时间:2008-10-16  
你这么写结果应该是不对的。
联合查询中你的COUNT(订单ID)应该都改为COUNT(DISTINCT 订单ID),否则数目会多很多。

据我所知,一般来说联合查询比子查询的效率要高,但是没有子查询用起来方便直接,比如你的例子,就要注意我上面提到的问题。
0 请登录后投票
   发表时间:2008-10-16  
引用

1.子查询和联合查询的区别有几点?
2.子查询改写成联合查询后的SQL语句是否错误?
3.在实际的操作过程中,我们如何写健壮的SQL语句?


1.两者的区别主要是在效率上,INNER JOIN通常效率比IN高许多
一般应当避免用IN
当两张表的关系是1:1的时候,可以直接将IN逻辑改写成为INNER JOIN
当两张表的关系是1:N的时候,直接改写为INNER JOIN就会导致迪卡尔积
从而得到重复记录
这时候应当采用以下形式
SELECT 
    雇员.雇员ID,
    雇员.姓氏,
    雇员.名字,
    雇员.邮政编码,
    雇员.城市,
    雇员.地址,
    雇员.家庭电话,
    X.CNT
FROM 雇员 
INNER JOIN (
    SELECT 
        订单.雇员ID,
        COUNT(*) AS CNT
    FROM 订单
    GROUP BY 订单.雇员ID 
    HAVING COUNT(*) > 100 
) X ON
    雇员.雇员ID = X.雇员ID


当然,当订单表中数据很多的时候,上面的这个SQL语句可能仍然有效率问题
最简单的解决办法是在雇员加一个“订单数”的字段
每次订单插入/删除的时候修改这个字段即可

3.在实际写联合查询语句的时候,为了写出正确的SQL语句
最要紧的就是理清表与表之间的关系,
在处理1:N,N:M关系的时候,注意避免迪卡尔积
2 请登录后投票
   发表时间:2008-11-12  
谢谢你的恢复
0 请登录后投票
   发表时间:2008-11-12  
谢谢你的虔诚回复,不过在SQL方面我还要继续努力
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics