sql:按多个相关字段分组(日期,工作日,月份)

时间:2016-08-02 16:47:53

标签: mysql group-by

我正在处理SQL任务。目标是在特定月份的航班表中知道平均有多少航班。

输入表格: 航班

id              BIGINT
dep_day_of_week varchar (255)
dep_month       varchar (255)
dep_date        text

航班表的一个例子。同一日期可能有多个条目。

id  dep_day_of_week  dep_month   dep_date
1   Thursday         January     4/7/2005 15:24:00
2   Friday           February    5/6/2005 12:12:12
3   Friday           February    5/6/2005 15:12:12

我读了一个解决方案如下:

SELECT a.dep_month,
       a.dep_day_of_week,
       AVG(a.flight_count) AS average_flights
  FROM (
        SELECT dep_month, dep_day_of_week, dep_date, 
         COUNT(*) AS flight_count
        FROM flights
        GROUP BY 1,2,3
       ) a
 GROUP BY 1,2
 ORDER BY 1,2;

我的问题是在子查询中计算每天的航班数量:

SELECT dep_month, dep_day_of_week, dep_date, COUNT(*) AS flight_count
FROM flights
GROUP BY 1,2,3

由于 dep_month dep_day_of_week dep_date 是三个相关属性, dep_date 可能是最详细的这三个决议。所以我认为GROUP BY 1,2,3将执行与GROUP BY 3相同的功能。

为了检查可能存在的差异,我使用count(*) from ..。选择上述子查询产生的所有术语

Select count(*) from (
    SELECT dep_month, dep_day_of_week, dep_date, COUNT(*) AS flight_count
    FROM flights
    GROUP BY 1,2,3 or Group Group by 3)

在输出中,GROUP BY 1,2,3GROUP BY 3的计数分别为447和441。为什么这两种分组方法有什么区别?

更新

感谢@trincot出色的答案。我使用他建议的代码,发现输入数据库不一致。

SELECT   dep_date, count(distinct dep_month), count(distinct dep_day_of_week)
FROM     flights
GROUP BY dep_date
HAVING   count(distinct dep_month) > 1
    OR   count(distinct dep_day_of_week) > 1

输出:

dep_date    count(distinct dep_month)   count(distinct dep_day_of_week)
1/16/2001   1   2
10/25/2003  1   2
2/23/2000   1   2
3/29/2001   1   2
4/3/2001    1   2
5/13/2000   1   2

具体而言,数据库会为1/16/2001 8:25:00指定星期一,为1/16/2001 7:56:00指定星期二。这就是不一致的原因。

1 个答案:

答案 0 :(得分:1)

由于日期字段具有时间组件,因此子查询中的count(*)每次都将为1,因为时间组件将不同并生成新组。你的小组实际上是每秒。

您可以在没有子查询的情况下获得结果,如下所示:

select   dep_month,
         dep_day_of_week,
         count(*) /
             count(distinct substring_index(dep_date, ' ', 1)) avg_flights
from     flights
group by dep_month,
         dep_day_of_week

这会计算所有航班记录,并按照这些航班所在的不同日期的数量进行划分。仅通过在空格之前拍摄部分来提取日期。

请注意,这意味着当您在特定日期没有记录时,这一天将不计入平均值,并可能给人一种错误的印象。例如,如果1月份只有一个星期五你有飞行(让他们说10个星期五),但是1月份有4个星期五,你仍然可以得到10个星期五,即使2.5分是更合理。

关于计数差异

您声明此查询返回447条记录:

Select count(*) from (
    SELECT dep_month, dep_day_of_week, dep_date, COUNT(*) AS flight_count
    FROM flights
    GROUP BY 1,2,3)

这只有441:

Select count(*) from (
    SELECT dep_month, dep_day_of_week, dep_date, COUNT(*) AS flight_count
    FROM flights
    GROUP BY 3)

这似乎表明您在多个记录中具有相同的日期,但在前两列中的一列中存在差异,这将是不一致的。你可以找到这个查询:

SELECT   dep_date, count(distinct dep_month), count(distinct dep_day_of_week)
FROM     flights
GROUP BY dep_date
HAVING   count(distinct dep_month) > 1
    OR   count(distinct dep_day_of_week) > 1

在健康的数据集中,此查询应返回0条记录。如果它返回记录,您将在至少一条记录中获得未正确设置月份的日期,或者至少在一条记录中未正确设置星期几。