【问题标题】:Relatively have Count(For that Day), Count for last 10 days and Count of last 20 days for each Vehicle相对有 Count(For that Day), Count for last 10 days and Count of last 20 days for each Vehicle
【发布时间】:2020-06-24 16:43:56
【问题描述】:

我正在尝试查看当天车辆的销售情况并创建另外两个列,告诉我过去 10 天的销售计数和过去 20 天的销售计数。同一天和同一辆车可能有多个销售。我的目标是获取 Distinct Vehicle and Date 并查看他们的销量。

N 天数应与该行的日期相关。

我的数据如下:

 Vehicle_ID       Sales_Date
 X500             01/03/2020 02:00:00 PM
 X500             01/11/2020 05:00:00 PM
 X500             01/25/2020 06:00:00 PM
 X500             01/25/2020 01:00:00 PM
 X500             02/13/2020 06:00:00 PM
 X500             02/21/2020 02:00:00 PM

我的目标表应该是这样的

 Vehicle_ID       Sales_Date     Sales_Count    Sales_Count_last_10     Sales_Count_last_20
 X500             01/03/2020         1                 1                      1
 X500             01/11/2020         1                 2                      2
 X500             01/25/2020         2                 2                      3
 X500             02/13/2020         1                 1                      4
 X500             02/21/2020         1                 2                      2

我尝试了以下查询:

SELECT TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY') Sales_Date1, Vehicle_ID, 
       COUNT(*) OVER (PARTITION BY Vehicle_ID, TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY')) SALES_COUNTS,
       SUM(CASE WHEN TO_DATE(Sales_Date) BETWEEN TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY') - 10 AND TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY')
                    THEN 1 ELSE 0 END) OVER (PARTITION BY Vehicle_ID, TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY'))
                    Sales_Count_last_10,
      SUM(CASE WHEN TO_DATE(Sales_Date) BETWEEN TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY') - 20 AND TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY')
                    THEN 1 ELSE 0 END) OVER (PARTITION BY Vehicle_ID, TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY'))
                    Sales_Count_last_10
FROM TABLE1

它只是为 Sales_Count、Sales_Count_last_10 和 Sales_Count_last_20 创建了相同的值。这是 N 天的列只是 Sales_Count 的重复

我也尝试了以下查询。

SELECT TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY') Sales_Date1, Vehicle_ID, COUNT(*) SALES_COUNTS,
       SUM(CASE WHEN TO_DATE(Sales_Date) BETWEEN TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY') - 10 AND TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY')
                    THEN 1 ELSE 0 END) Sales_Count_last_10,
       SUM(CASE WHEN TO_DATE(Sales_Date) BETWEEN TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY') - 20 AND TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY')
                    THEN 1 ELSE 0 END) Sales_Count_last_20
FROM TABLE1
GROUP BY Vehicle_ID, TO_DATE(TO_CHAR(Sales_Date, 'MM/DD/YYYY'), 'MM/DD/YYYY')

它显示了与上一个查询相同的结果。复制 N-days 列的 Sales_Count。

请帮我解决这个问题。

【问题讨论】:

    标签: sql oracle group-by count window-functions


    【解决方案1】:

    您可以使用sum 的窗口子句来指定要查看多少天。

    使用range between N preceding and current row,它包括从当前行 - N 到当前的所有值

    这给出了:

    with rws as (
      select 'X500' vehicle_id, to_date ( '01/03/2020 02:00:00 PM', 'mm/dd/yyyy hh:mi:ss pm' ) sales_date from dual union all
      select 'Y300' vehicle_id, to_date ( '01/11/2020 05:00:00 PM', 'mm/dd/yyyy hh:mi:ss pm' ) sales_date from dual union all
      select 'Q240' vehicle_id, to_date ( '01/25/2020 06:00:00 PM', 'mm/dd/yyyy hh:mi:ss pm' ) sales_date from dual union all
      select 'Q240' vehicle_id, to_date ( '01/25/2020 01:00:00 PM', 'mm/dd/yyyy hh:mi:ss pm' ) sales_date from dual union all
      select 'F310' vehicle_id, to_date ( '02/13/2020 06:00:00 PM', 'mm/dd/yyyy hh:mi:ss pm' ) sales_date from dual union all
      select 'E990' vehicle_id, to_date ( '02/21/2020 02:00:00 PM', 'mm/dd/yyyy hh:mi:ss pm' ) sales_date from dual 
    )  
      select distinct trunc ( sales_date ), vehicle_id, 
           count(*) over (
             partition by vehicle_id, trunc(sales_date) 
           )        sales_counts,
           count (*) over ( 
             order by trunc ( sales_date )
             range between 10 preceding and current row
           ) last_10,
           count (*) over ( 
             order by trunc ( sales_date )
             range between 20 preceding and current row
           ) last_20
    from rws
    order  by 1, 2
    
    TRUNC(SALES_DATE)       VEHICLE_ID    SALES_COUNTS    LAST_10    LAST_20   
    03-JAN-2020 00:00:00    X500                        1          1          1 
    11-JAN-2020 00:00:00    Y300                        1          2          2 
    25-JAN-2020 00:00:00    Q240                        2          2          3 
    13-FEB-2020 00:00:00    F310                        1          1          3 
    21-FEB-2020 00:00:00    E990                        1          2          2 
    

    PS 如果您想从 Oracle 数据库中的日期中删除时间组件,只需 trunc 即可。比to_date(to_char(..., 'fmt'))简单多了!

    【讨论】:

    • 谢谢!!对于 last_10 和 last_20,我们需要它们仅按 Vehicle_ID 分组,对吗?否则它将记录过去 10 天内所有车辆的记录。
    • 所以,last_10 和 last_20 没有被正确捕获
    • 如果您想在每辆车的最后 N 天进行销售,那么是的,您需要 partition by vehicle_id。原始数据和请求的输出建议过去 N 天内所有车辆的总数。
    【解决方案2】:

    这看起来是一个使用窗口范围规范(以及聚合)的好地方:这个子句接受一个定义窗口的间隔,这就是您似乎正在寻找的:

    select
        vehicle_id,
        trunc(sales_date) sales_day,
        count(*) sales_count,
        sum(count(*)) over(
            order by trunc(sales_date)
            range between interval '10' day preceding and current row
        ) sales_count_last_10,
        sum(count(*)) over(
            order by trunc(sales_date)
            range between interval '20' day preceding and current row
        ) sales_count_last_20
    from mytable
    group by vehicle_id, trunc(sales_date)
    order by sales_day
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-15
      • 2023-01-17
      • 1970-01-01
      • 1970-01-01
      • 2022-12-27
      • 1970-01-01
      • 2022-07-22
      • 2020-06-13
      相关资源
      最近更新 更多