bingfengCoder
V2EX  ›  Java

请教一个 SQL 的问题,来个大佬帮忙丁真下

  •  
  •   bingfengCoder · Jan 31, 2024 · 5864 views
    This topic created in 1008 days ago, the information mentioned may be changed or developed.
    SELECT
    	p.project_code AS 项目编码,
    	p.project_name AS 项目名称,
    	count( e.id ) AS 建筑数量,
    	count( d.id ) AS 设备数量 
    FROM
    	`emp_project` p
    	LEFT JOIN `architecture` e ON p.id = e.`project_id` 
    	AND e.`is_active` = 1 
    	AND e.`level` = 30 
    	AND e.`source_type` = 'Z'
    	LEFT JOIN `project_device` d ON p.id = d.project_id 
    	AND d.is_active = 1 
    	AND d.device_type IN ( 1, 2, 3, 4 ) 
    WHERE
    	p.`is_active` = 1 
    	AND p.`source_type` = 'Z' 
    GROUP BY
    	p.id
    
    SELECT
    	p.project_code AS 项目编码,
    	p.project_name AS 项目名称,
    	en.encount AS 建筑数量,
    	de.decount AS 设备数量 
    FROM
    	`emp_project` p
    	LEFT JOIN ( SELECT `project_id`, count(*) AS encount FROM `architecture` WHERE `level` = 30 AND `is_active` = 1 
    	AND `source_type` = 'Z' GROUP BY `project_id` ) en ON p.id = en.`project_id`
    	LEFT JOIN (
    	SELECT
    		`project_id`,
    		count(*) AS decount 
    	FROM
    		`project_device` 
    	WHERE
    		`is_active` = 1 
    		AND `device_type` IN ( 1, 2, 3, 4 ) 
    	GROUP BY
    		`project_id` 
    	) de ON p.id = de.project_id 
    WHERE
    	p.`is_active` = 1 
    	AND p.`source_type` = 'Z'
    

    这两段 sql 在同一个库里执行,结果天差地别,但是从连接和分组以及查询条件来看,感觉不出来有什么差异,大佬们能不能一眼丁真帮看下原因

    33 replies  •  2024-02-01 15:36:51 +08:00
    hxpmc
    hxpmc
    Jan 31, 2024
    1
    第二个慢?
    bingfengCoder
    bingfengCoder
    OP
    Jan 31, 2024
    2
    @hxpmc 不是快慢的问题,现在不考虑性能,它们查询结果完全不一样,就是 count 值差别很大,但是从直觉上去读这两个 sql ,总感觉又没毛病
    Xinu
    Xinu
    Jan 31, 2024
    3
    没去问问 gpt 吗 现在 sql 问题一律先问 gpt
    bingfengCoder
    bingfengCoder
    OP
    Jan 31, 2024
    4
    @Xinu 问过了,结果就是人工智障,它告诉我这是两个相似的 sql ,结果也应该相似。。。。但是实际执行结果 count 相差很大
    gerryzhu0033
    gerryzhu0033
    Jan 31, 2024❤️1
    5
    left join 和 right join 后面不要用 where ,用了 where 就变普通 join 了
    inkmulberry
    inkmulberry
    Jan 31, 2024
    6
    感觉上应该是第一个 count 更大
    houfeibin
    houfeibin
    Jan 31, 2024❤️1
    7
    第二种结果是对的
    ZZ74
    ZZ74
    Jan 31, 2024❤️1
    8
    注意 left join
    第一句 p 中 project id 就算 e ,d 中没有对应的 也会被 count
    第二句 就不会有问题

    而且现在 sql 都那么宽泛了吗? 第一句 sql 你 count 的话 不应该是 group by project_code 和 name 为啥要是 id...
    怎么说呢 你这两个统计值应该做成两个 sql 用 inner join....
    jorinabill111
    jorinabill111
    Jan 31, 2024
    9
    逆天丁真
    8355
    8355
    Jan 31, 2024
    10
    sql1 的 join 2 次纬度差异 导致的 count 数量不对吧
    从来没有想过这种魔法的操作

    你的主 sql 本身与 e/d 表条件没有任何关联就应该单独直接 sql count
    8355
    8355
    Jan 31, 2024
    11
    @ZZ74 确实 group by 主表 id 的操作还是第一次见。。。 十分之 6
    bingfengCoder
    bingfengCoder
    OP
    Jan 31, 2024
    12
    @inkmulberry 是的,第一个 count 会比较大,但是这种大是不准确的,找不到原因
    sivl6p
    sivl6p
    Jan 31, 2024
    13
    笛卡尔乘积造成的
    bingfengCoder
    bingfengCoder
    OP
    Jan 31, 2024
    14
    @ZZ74 试过 group by project_code,name 和 group by id 结果是一样的,count 都不准确。。。。
    ZZ74
    ZZ74
    Jan 31, 2024
    15
    @bingfengCoder
    注意这句 注意 left join
    第一句 p 中 project id 就算 e ,d 中没有对应的 也会被 count
    ivvei
    ivvei
    Jan 31, 2024 via Android
    16
    语法都不对,这是 mysql 吧?
    F281M6Dh8DXpD1g2
    F281M6Dh8DXpD1g2
    Jan 31, 2024
    17
    建议你再学学
    真是一眼就能看出区别
    mytoroto
    mytoroto
    Jan 31, 2024
    18
    同意楼上,再学学,你这是基本功有问题啊
    mytoroto
    mytoroto
    Jan 31, 2024
    19
    @mytoroto 回错楼了
    bingfengCoder
    bingfengCoder
    OP
    Jan 31, 2024
    20
    @mytoroto 能细说下吗
    bingfengCoder
    bingfengCoder
    OP
    Jan 31, 2024
    21
    @liprais 能展开说下吗,想知道问题出在哪里
    sorcerer
    sorcerer
    Jan 31, 2024 via Android
    22
    最简单的情况
    表 1 一条记录 表二满足 join 条件的有两条记录 也就是 project id 一样的有两条 表三 project id 一样的有 3 条

    这样通过方法 1 关连后 最终表里有 6 条记录 ,count 表二和表三的 proj id 都等于 6 方法二最终结果只有一条,凑 count 表二 表三的结果分边为 2 和 3
    cccmm
    cccmm
    Jan 31, 2024
    23
    architecture 表或 project_device 表的 project_id 有重复?
    kkwa56188
    kkwa56188
    Feb 1, 2024
    24
    第一个: 你 group by 什么字段, 就只能 select 什么字段, 其余列需要是 agg 函数, 不知道怎么跑的起来的.

    第二个: (看了一半 算了, 你为什么要这么写, 还不如重写, 见下面三)

    三: 这本身是个简单的查询, p 主表就不动它了, 不 join 不 GroupBy, 两个子表的话 再在子查询里 join 完了再 count 就好了,
    这样: select p.id, ( 子查询 1 select count(e.id) ), ( 子查询 2 select count(d.id)) from p
    xuanbg
    xuanbg
    Feb 1, 2024
    25
    @bingfengCoder 第一种的 count 其实是右表的行数,第二种 count 的是右表 id 的个数。
    在 count 函数里面加 distinct ,写成以下的代码,结果就一致了:
    SELECT
    p.project_code AS 项目编码,
    p.project_name AS 项目名称,
    count(distinct e.id ) AS 建筑数量,
    count(distinct d.id ) AS 设备数量
    FROM
    `emp_project` p
    LEFT JOIN `architecture` e ON p.id = e.`project_id`
    AND e.`is_active` = 1
    AND e.`level` = 30
    AND e.`source_type` = 'Z'
    LEFT JOIN `project_device` d ON p.id = d.project_id
    AND d.is_active = 1
    AND d.device_type IN ( 1, 2, 3, 4 )
    WHERE
    p.`is_active` = 1
    AND p.`source_type` = 'Z'
    GROUP BY
    p.id
    bingfengCoder
    bingfengCoder
    OP
    Feb 1, 2024
    26
    @xuanbg 试了下,结果一致了,感谢大佬
    bingfengCoder
    bingfengCoder
    OP
    Feb 1, 2024
    27
    @kkwa56188 25 楼 大佬给出了 详细的写法,group by 可以跑起来的,结果一致了
    M48A1
    M48A1
    Feb 1, 2024 via iPhone
    28
    @ZZ74 相同想法,第一个 group by 为什么不报错…
    bingfengCoder
    bingfengCoder
    OP
    Feb 1, 2024
    29
    @M48A1 现在第一个 group by 不仅不会报错,还能得到正确的结果了 详见 25 楼 XD
    bingfengCoder
    bingfengCoder
    OP
    Feb 1, 2024
    30
    不知道为什么大家会把第一种 group by 主表字段 当成邪教用法,但是通过有效的 left join 可以很好的避免子查询产生的次数,我不太喜欢写很多个子查询然后 一个个 join ,更倾向直接 join 然后一把 group by 梭,感觉要来的更加方便
    M48A1
    M48A1
    Feb 1, 2024 via iPhone
    31
    @bingfengCoder 什么版本呀,我被淘汰了
    server sql 必须加满 group by.
    bingfengCoder
    bingfengCoder
    OP
    Feb 1, 2024
    32
    @M48A1 用的 mysql 5.7 ,mysql 8 加了 ONLY_FULL_GROUP_BY 模式 也是需要加满的
    Cruzz
    Cruzz
    Feb 1, 2024
    33
    没仔细看,但是我感觉第一个种写法 count 的值有重复的。去重下?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3006 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 89ms · UTC 12:08 · PVG 20:08 · LAX 04:08 · JFK 07:08
    ♥ Do have faith in what you're doing.