欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL非标准SQL写法问题记录 博客分类: MySQL mysqlGROUP BY 

程序员文章站 2024-02-25 20:38:57
...
如下SQL:
SELECT  t.message_id,
  t.product_id,
  t.drug_code,
  t.analysis_result_type,
  t.analysis_type,
  t.severity,
  (
    CASE
      t.drug_code 
      WHEN '001' 
      THEN 
      (SELECT 
        sd.chineseProductName 
      FROM
        `149wuhu_platform`.tb_product sd 
      WHERE sd.id = t.product_id) 
      ELSE b.drug_id 
    END
  ) product_name,
  IF(
    b.source = '配伍禁忌' 
    AND b.message_id LIKE '10%',
    t.message,
    b.message
  ) message,
  SUM(COUNT) AS amount,
  '1' AS dataType,
  IFNULL(b.rule_type, 0) rule_type,
  IFNULL(c.apply_status, 0) apply_status,
  b.status_recipe alert_status 
FROM
  opt_alertmessage_statistic AS t 
  INNER JOIN `149wuhu_platform`.tb_drug_rule_message b 
    ON t.message_id = b.message_id 
  LEFT JOIN `149wuhu_platform`.base_message_review c 
    ON c.message_id = t.message_id 
    AND c.apply_user_id = 1 
WHERE t.key_date >= '2016-03-01' 
  AND t.key_date <= '2016-04-05' 
  AND (t.zone_id IN (2, 3, 4, 5, 6, 7, 8, 9)) 
GROUP BY t.message_id,t.product_id


上述执行结果总数是:2525行

但如果去掉最后面的:GROUP BY t.message_id,t.product_id 后执行结果却只有一条记录,这显然不符合正常逻辑(正常情况下查询结果是不低于2525行的),
造成此问题原因是上述SQL是非标准SQL,标准SQL要求中要求 SELECT后的查询字段必须和GROUP BY后的字段是相同的,即不能多也不能少!

备注:
1.在group by 里的列,可以直接出现在结果列(也可以少)。
2.不在group by 里的列,在经过聚合函数计算后可以出现在结果列(也可以多)。

PS:Oracle中是不支持此非标准写法的。

附加:
根据SQL92国际标准:
http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

If T is a grouped table, then each <column reference> in each <value
expression> that references a column of T shall reference a grouping
column or be specified within a <set function specification>.

简单的说,如果一个查询用了 group by,那么 select 可选择的 列 有两个可能 1. group by
中指定的列(或者其计算值),2. 聚合函数计算后的其它(非group by指定的)列。

而 MySQL 自作聪明(关闭ONLY_FULL_GROUP_BY),不符合国际标准,容忍了我们犯错,这也是引起我们自己混乱的原因。

举个例子:
gender age
男 11
女 22
男 33

这语句你们指望得到什么结果?
SELECT gender,age FROM USER GROUP BY gender

是:
男 11
女 22
还是:
女 22
男 33
这本来就不是个正确的SQL语句!
正确的语句应该改为这样:
SELECT gender,MIN(age) FROM USER GROUP BY gender

也就是将非group by的列放入某个聚合函数里。

建议以后写语句严格要求自己,不要让MySQL将我们带入歧途!
可能的话将ONLY_FULL_GROUP_BY打开。

MySQL查询原理及其慢查询优化案例
相关标签: mysql GROUP BY