【问题标题】:Strange results of mysql query with GROUP BY and ORDER BY使用 GROUP BY 和 ORDER BY 的 mysql 查询的奇怪结果
【发布时间】:2014-05-30 14:00:23
【问题描述】:

只是想知道是否有人可以在这里发现任何明显错误的地方。我在 MySQL 中使用 SELECT 得到了奇怪的结果。我看不出查询有什么问题,所以我想知道是否有一些数据将其丢弃,但数据看起来还不错。所以我猜我的 sql 出了点问题!

我有 2 张桌子,CITY 和 WEATHER:

CITY:
  CITY_ID    INT(3)
  CITY_NAME  VARCHAR(100)

WEATHER:
  CITY_ID   INT(3)
  SDATE     DATETIME
  TEMP      INT(3)
  RAIN      INT(3)

CITY 表非常小;每个定义的城市一行。

WEATHER 表有很多行;它对每个城市都有预测(每天几次)。还保存历史预测,所以那里有几个月前的数据。

我想在每一行上查看每个城市每个月的摘要。 我想要一个月的所有城市信息,然后是上个月等。 在每个月内,我希望结果按温度(降序)然后下雨(降序)排序。

所以,我的查询:

 SELECT     a.city_name                   as CITY
          , DATE_FORMAT(b.sdate, '%M %Y') as MONTH
          , ROUND(avg(b.temp))            as AVG_TEMP_C
          , SUM(b.rain)                   as RAIN
 FROM       CITY a , WEATHER b
 WHERE      a.city_id = b.city_id
 GROUP BY   a.city_name , DATE_FORMAT(b.sdate, '%M %Y')
 ORDER BY   sdate desc,  ROUND(avg(b.temp)) desc , SUM(b.rain) desc;

我期望的结果:

CITY         MONTH  TEMP   RAIN
ISTANBUL     June   20     0
MUNICH       June   15     9
PARIS        June   15     7
MILAN        June   14     8
ISTANBUL     May    19     22
etc.

我得到的结果:

CITY         MONTH  TEMP   RAIN
MUNICH       June   15     9
MILAN        June   14     8
ISTANBUL     June   20     0
PARIS        June   15     7
ISTANBUL     May    19     22
etc.

就像我说的,数据看起来没问题,所以我想我在所有格式、连接、分组和排序方面都遗漏了一些东西..

【问题讨论】:

  • 你能用你的样本数据集设置sqlfiddle.com例子吗
  • 也许您需要通过DATE_FORMAT(b.sdate, '%M %Y') 而不是date 自己订购。示例数据将有助于确定。
  • 感谢您的回复,但按 DATE_FORMAT(b.sdate, '%M %Y') desc 将按字母顺序按月份排序(所以 May, March, June, April)

标签: mysql sql group-by sql-order-by


【解决方案1】:

这是您的查询,带有显式连接和更合理的表别名(表缩写而不是任意字母):

 SELECT     c.city_name                   as CITY,
            DATE_FORMAT(w.sdate, '%M %Y') as MONTH,
            ROUND(avg(w.temp))            as AVG_TEMP_C,
            SUM(w.rain)                   as RAIN,
 FROM       CITY a JOIN
            WEATHER w
            ON c.city_id = w.city_id
 GROUP BY   c.city_name , DATE_FORMAT(w.sdate, '%M %Y')
 ORDER BY   sdate desc,  ROUND(avg(w.temp)) desc , SUM(w.rain) desc;

order by 中的第一列是sdate。但是,这不包含在您的 group by 子句中。因此,MySQL 会从不确定的行中为每个城市选择 sdate 的值(在其他数据库中,这会产生错误)。

改为将您的 order by 更改为使用月份和年份:

 ORDER BY   year(sdate) desc,  month(sdate) desc, ROUND(avg(w.temp)) desc , SUM(w.rain) desc;

【讨论】:

  • 在这种情况下使用ORDER BY year(sdate) desc, month(sdate) desc 肯定会导致用于排序的 sdate 的不确定行值?还是我错过了什么?
  • 宾果游戏!非常感谢!所以,只是为了确认一下,我的加入版本没问题,问题出在日期的 ORDER BY 上?我确实认为如果是 Oracle(例如)它会产生错误。没有抛出错误,我收集到 mysql 的语法是“好的”。当然,仅仅因为语法是“好的”并不意味着它会做你想做的事!我明白为什么“按 sdate 排序”不起作用,但我仍然不明白使用 year() 和 month() 是如何解决这个问题的。
  • 我错过了一些东西。虽然它使用 sdate 的不确定行值,但它将使用的任何 sdate 值都将共享相同的月份和年份。
【解决方案2】:

您正在按聚合结果表中的 sdate 排序,但不是聚合函数的主题。因此 mysql 采用与其他条件匹配的任何 sdate 值(可能是第一个?)并按此值排序。

【讨论】:

    【解决方案3】:

    我也很想恢复每个城市/月的最大日期,然后在 ORDER BY(格式化为 CCYYMM 格式)中使用它来让它们按正确的顺序排列。

    类似这样的:-

    SELECT a.city_name as CITY , 
            DATE_FORMAT(b.sdate, '%M %Y') as MONTH , 
            MAX(b.sdate) AS max_date,
            ROUND(avg(b.temp)) as AVG_TEMP_C , 
            SUM(b.rain) as RAIN 
    FROM CITY a 
    INNER JOIN WEATHER b 
    ON a.city_id = b.city_id 
    GROUP BY a.city_name , MONTH
    ORDER BY DATE_FORMAT(max_date, '%Y%m') desc, AVG_TEMP_C desc , RAIN desc;
    

    或稍有不同:-

    SELECT a.city_name as CITY , 
            DATE_FORMAT(b.sdate, '%M %Y') as MONTH , 
            MAX(b.sdate) AS max_date,
            ROUND(avg(b.temp)) as AVG_TEMP_C , 
            SUM(b.rain) as RAIN 
    FROM CITY a 
    INNER JOIN WEATHER b 
    ON a.city_id = b.city_id 
    GROUP BY a.city_name , MONTH
    ORDER BY YEAR(max_date) desc, MONTH(max_date) desc, AVG_TEMP_C desc , RAIN desc;
    

    【讨论】:

      猜你喜欢
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 2019-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多