在 SQL 查询中计算随后两个月的不同行程

Posted

技术标签:

【中文标题】在 SQL 查询中计算随后两个月的不同行程【英文标题】:calculate different trips over two subsequent month in a SQL query 【发布时间】:2021-12-29 22:11:03 【问题描述】:

我有一个简单的表格,其中包含不同日期的旅行。

trip_id start_date end_date
160320 2017-12-31 20:40:25 UTC 2017-12-31 20:45:25 UTC
160321 2018-01-12 21:01:51 UTC 2018-01-12 22:01:51 UTC

我只是想创建一个显示这些字段的 SQL 查询。

年 月 trips_this_month, trips_previous_month difference_from_previous_month (count_this_month - count_previous_month) is_increased(是一个布尔列,如果我们看到增加,则为真,假 除此以外) 更新: 我可以总结一下并编写一个简单的查询来获取它们,但我仍然觉得我可以优化这个查询。任何帮助将不胜感激。
    SELECT
    year,
    month,
    trips_this_month,
    trips_previous_month,
    case when difference_from_previous_month < 0 then false else true end as is_increased
FROM    
(SELECT    
    year,
    month,
    number_of_trips AS trips_this_month,
    LAG(number_of_trips,1,0) over (order by year,month) AS trips_previous_month,    
    number_of_trips - LAG(number_of_trips,1,0) OVER(order by year,month) AS difference_from_previous_month,    
    FROM(
        SELECT EXTRACT(Month FROM start_date) AS month,
               EXTRACT(Year FROM start_date) AS year,
               COUNT(*) as number_of_trips
               FROM a_table
    group by  month ,year
    )
    order by year, month
    limit 100
)
    

但我忍不住要做更多。感谢您为完成它提供进一步的帮助。

【问题讨论】:

select version(); 显示什么? 您的样本数据不是下个月。此外,您尝试的查询只是采用month 没有任何year 条件,因此2017-01 将与2018-01 一起计算。 @FanoFN 谢谢,我更新了我的问题。我需要优化 select-in-select 查询。有什么建议吗? 我猜你想返回下个月的结果,即使那个月没有旅行,对吧? @FanoFN 是的,我需要计算所有月份,我在上面的查询中面临的问题是我必须使用别名'as'来命名列,但我不能在相同的 SELECT 查询,所以我不得不将结果作为后续的 SELECT 查询传递给另一个 SELECT。这看起来没有优化,但不幸的是我不知道其他方式。 【参考方案1】:

考虑使用标准化的月份日期来比较当前和前几个月的聚合:

WITH sub AS (
    SELECT 
       DATE_SUB(
           DATE_ADD(LAST_DAY(start_date), INTERVAL 1 DAY), 
           INTERVAL 1 MONTH
       ) AS month_year,
       COUNT(*) AS number_of_trips
    FROM a_table
    GROUP BY month_year
), calc AS (
    SELECT
       EXTRACT(YEAR FROM curr.month_year) AS year,
       EXTRACT(MONTH FROM curr.month_year) AS month,
       COALESCE(curr.number_of_trips, 0) AS trips_this_month,
       COALESCE(prev.number_of_trips, 0) AS trips_previous_month
    FROM sub AS curr
    LEFT JOIN sub AS prev
        ON prev.month_year = DATE_SUB(curr.month_year, INTERVAL 1 MONTH) 
)

SELECT
    year,
    month,
    trips_this_month,
    trips_previous_month,
    trips_this_month - trips_previous_month AS difference_from_previous_month,
    (trips_this_month - trips_previous_month) > 0 AS is_increased
FROM calc

【讨论】:

感谢您的回答,我正在尝试您的回答。我正在使用谷歌云大查询。我是 Google Big Query 的新手。不幸的是它不支持必须的功能 我看到你更新了标签。这回答了假设的 mysql。但是,大多数日期函数似乎都受支持。见BigQuery Date Functions。虽然我确实用EXTRACT 替换了YEAR()MONTH()。见编辑。 谢谢。是的,我更新了标签,就在意识到 BigQuery 在这里也有一个标签并将你的标签设置为答案之后。虽然我有一个问题。我比较了性能,发现响应时间差别不大。不确定我们是否可以进一步优化它【参考方案2】:

这是一个 MySQL 答案,是在 OP 更改标签之前发布的。 我不使用 Bigquery,所以我不确定我的答案需要调整多少才能在 Bigquery 中使用。我所知道的是,我已经测试了 OP 的原始查询以及来自 MySQL 服务器上接受的答案的查询,它可以工作,所以我假设我建议的(MySQL)答案不需要很多调整就可以在 Bigquery 中工作。


试试这个:

WITH RECURSIVE cte AS (
SELECT MIN(start_date) minstdt, MAX(start_date) maxstdt FROM mytable
UNION ALL
SELECT minstdt+INTERVAL 1 MONTH, maxstdt FROM cte 
       WHERE minstdt+INTERVAL 1 MONTH <= maxstdt )
       
SELECT year,
       month,
       number_of_trips,
       number_of_trips-IFNULL(prev_month_number_of_trips,0) AS This_month_vs_prev_month,
       IF(number_of_trips > prev_month_number_of_trips,1,0) AS Is_increased
FROM
(SELECT
     YEAR(cte.minstdt) AS year,
     MONTH(cte.minstdt) AS month,
     SUM(CASE WHEN start_date IS NULL THEN 0 ELSE 1 END) AS number_of_trips,
     LAG(SUM(CASE WHEN start_date IS NULL THEN 0 ELSE 1 END)) 
         OVER (ORDER BY YEAR(cte.minstdt), MONTH(cte.minstdt)) AS prev_month_number_of_trips
    FROM cte 
LEFT JOIN mytable 
 ON YEAR(cte.minstdt)=YEAR(start_date) 
  AND MONTH(cte.minstdt)=MONTH(start_date) 
GROUP BY year, month) V
ORDER BY year, month;
    我使用递归公用表表达式 (cte) 根据表的 start_date 中出现的最小和最大日期生成日期。 我已将 EXTRACT() 替换为 YEAR()MONTH() 函数要稍微短一些。 我LEFT JOINcte有数据表。

Demo fiddle

看看你能不能用这个。

【讨论】:

以上是关于在 SQL 查询中计算随后两个月的不同行程的主要内容,如果未能解决你的问题,请参考以下文章

sql 计算一个月几天

sql查询计算不同列和相邻行的两个日期之间的差异

前 3 个月的滚动总和 SQL Server

高德导航中怎么计算起点和终点之间行程的距离

查询两个日期相差的月数和剩下的天数

sql 查询每个月的记录数量