询问分组依据并在Mysqli查询中排序

时间:2018-12-25 07:02:55

标签: mysqli

首先,对于这个论坛中是否有类似的帖子,我深表歉意,请高手帮助我,我需要一种有效的方式来查询我的visitor表的摘要,我拥有类似的表: 表格名称:table_visitor

+----+------------+---------+---------------------+
| id |    city    | country |     time_visit      |
+----+------------+---------+---------------------+
|  1 | london     | uk      | 2017-11-02 13:01:00 |
|  2 | new york   | usa     | 2017-11-13 00:23:00 |
|  3 | london     | uk      | 2017-11-17 10:23:00 |
|  4 | bristol    | uk      | 2017-11-22 07:00:00 |
|  5 | texas      | usa     | 2017-11-30 04:10:00 |
|  6 | dublin     | ireland | 2017-12-02 13:01:00 |
|  7 | new york   | usa     | 2017-12-13 00:23:00 |
|  8 | london     | uk      | 2017-12-17 10:23:00 |
|  9 | bristol    | uk      | 2017-12-22 07:00:00 |
| 10 | london     | uk      | 2018-01-01 10:00:00 |
| 11 | washington | usa     | 2018-01-13 14:00:00 |
+----+------------+---------+---------------------+

我需要执行时间最短的高效查询,它可以产生单独的数据(通过对time_visit列进行排序,对城市和国家/地区列按字母顺序进行分组,计数和排序),如下所示。 表名称:visitor_summary

+----+------+-------+--------------------------------------------+-------------------------+
| id | year | month |                    city                    |         country         |
+----+------+-------+--------------------------------------------+-------------------------+
|  1 | 2017 |    11 | london(2),bristol(1),new york(1),texas(1)  | uk(3),usa(2)            |
|  2 | 2017 |    12 | bristol(1),dublin(1),london(1),new york(1) | uk(2),ireland(1),usa(1) |
|  3 | 2018 |     2 | london(1),washington(1)                    | uk(1),usa(1)            |
+----+------+-------+--------------------------------------------+-------------------------+

先谢谢高手。

1 个答案:

答案 0 :(得分:0)

这是一个棘手的报告问题。 GROUP_CONCAT函数可以执行您想要的操作,但是那将需要已经有了一张表格,其中包含每月和每年的城市及其总计数,或者国家及其总计数。因此,一种方法是进行汇总,首先按年份,月份和城市/国家/地区汇总,然后仅按年份和月份再次汇总,以获得所需的CSV报告。

SELECT
    t1.year,
    t1.month,
    t1.cities,
    t2.countries
FROM
(
    SELECT
        year,
        month,
        GROUP_CONCAT(t.city_label, '(', CAST(t.cnt AS CHAR(50)), ')') cities
    FROM
    (
        SELECT
            YEAR(time_visit) year,
            MONTH(time_visit) month,
            CONCAT(country, '-', city) AS city_label,
            COUNT(*) AS cnt
        FROM table_visitor
        GROUP BY YEAR(time_visit), MONTH(time_visit), CONCAT(country, '-', city)
    ) t
    GROUP BY year, month
) t1
INNER JOIN
(
    SELECT
        year,
        month,
        GROUP_CONCAT(t.country, '(', CAST(t.cnt AS CHAR(50)), ')') countries
    FROM
    (
        SELECT YEAR(time_visit) year, MONTH(time_visit) month, country, COUNT(*) AS cnt
        FROM table_visitor
        GROUP BY YEAR(time_visit), MONTH(time_visit), country
    ) t
    GROUP BY
        year, month
) t2
    ON t1.year = t2.year AND t1.month = t2.month
GROUP BY
    t1.year,
    t1.month;

enter image description here

Demo

请注意,在我的输出中,我同时使用城市名和国家名指城市。原因是给定的城市名称可能在各个国家/地区都不是唯一的。例如,美国俄亥俄州拥有一个名为伦敦的城市,因此仅在报告中使用伦敦可能就模棱两可。

如果要在城市或国家/地区列中订购CSV数据,请考虑将ORDER BYGROUP_CONCAT一起使用。

编辑:

从下面的评论看来,您的表可能非常大,此外,您可能需要经常在生产环境中运行此报告。我建议您将报告分为几部分。例如,您可以运行一个proc,该proc在每个年/月末使用上述查询。然后,它可以将结果记录插入建议的visitor_summary表中。这样,不必一次全部整理整个历史表就不会影响生产。