【问题标题】:MySQL case when involving week(), year(), curdate(), and weekday()涉及 week()、year()、curdate() 和 weekday() 时的 MySQL 案例
【发布时间】:2015-07-31 18:18:31
【问题描述】:

我有一个数据集,其中包含订单日期及其变体(week()、year()、weekday() 等)。当且仅当订单日期满足特定条件(例如,周 = 51,年 = 2015)时,我想创建对订单单位求和的逻辑。

我正在寻找的输出:

product_id, product_sku, 星期一_单位_售出, 星期二_单位_已售出, 星期三_单位_已售出, thursday_units_sold, friday_units_sold, 星期六_单位_售出, sunday_units_sold

这里需要注意的是,如果订单日期发生在上周,我只希望在那些日子出售单位。另外,我不希望这个计算依赖于 where 子句中的任何标准。我已经缩短了请求以使其保持简单,但实际上我将在一个 select 子句中查看不同的时间范围(迄今为止的生命、mtd、ytd 等)。

这是我目前无法使用的代码。

 select
    product_id,
    sku_code,
    case when week = current_week and year = current_year and weekday = 0 then sum(units_sold) end as monday_units,
    case when week = current_week and year = current_year and weekday = 1 then sum(units_sold) end as tuesday_units,
    case when week = current_week and year = current_year and weekday = 2 then sum(units_sold) end as wednesday_units,
    case when week = current_week and year = current_year and weekday = 3 then sum(units_sold) end as thursday_units,
    case when week = current_week and year = current_year and weekday = 4 then sum(units_sold) end as friday_units,
    case when week = current_week and year = current_year and weekday = 5 then sum(units_sold) end as saturday_units,
    case when week = current_week and year = current_year and weekday = 6 then sum(units_sold) end as sunday_units

from
    -- This table is at the order level whereas the final result rolls up into the product/sku level.
    (select
        order_date,
        order_id,
        product_id,
        sku_code,
        weekday(order_date) as weekday,
        week(order_date) as week,
        month(order_date) as month,
        year(order_date) as year,
        yearmonth(order_date) as yearmonth,
        units_sold,
        product_sales,
        -- I tried calculating this in each case when in the select statement above, 
        -- but moved it down here in an attempt to problem solve why my calculations aren't working.
        week((curdate() - interval 1 day)) as current_week, 
        year((curdate() - interval 1 day)) as current_year,
    from product_sales
    ) a

【问题讨论】:

  • 你在外部查询中没有遗漏GROUP BY sku_code, weekday 之类的东西吗?

标签: mysql


【解决方案1】:

我认为您可以简化查询:

select product_id, sku_code
     , year(order_date) as order_year
     , weekofyear(order_date) as order_week
     , sum(case weekday(order_date) when 0 then units_sold else 0 end) as monday_units
     , sum(case weekday(order_date) when 1 then units_sold else 0 end) as tuesday_units
     , sum(case weekday(order_date) when 2 then units_sold else 0 end) as wednesday_units
     , sum(case weekday(order_date) when 3 then units_sold else 0 end) as thursday_units
     , sum(case weekday(order_date) when 4 then units_sold else 0 end) as friday_units
     , sum(case weekday(order_date) when 5 then units_sold else 0 end) as saturday_units
     , sum(case weekday(order_date) when 6 then units_sold else 0 end) as sunday_units
from
    (
        select
            order_date,
            order_id,
            product_id,
            sku_code,
            units_sold,
            product_sales
        from product_sales
    ) as a
 -- Example of WHERE condition:
where year(order_date) = 2015 and weekofyear(order_date) = 51
group by product_id, sku_code, order_year, order_week;

由于表可能非常大,也许最好的方法是创建一个临时表,对其进行索引,然后从该临时表中进行选择。像这样的:

-- If the temp table exists, drop it
drop table if exists temp_product_sales;
-- Create a temporary table with the data you're interested.
-- I suggest you add the WHERE conditions in this SELECT, because it may
-- speed up the final SELECT.
-- Notice that I'm not grouping the data just yet... that will be done 
-- with the final SELECT
create temporary table temp_product_sales
        select
            order_date,
            order_id,
            product_id,
            sku_code,
            units_sold,
            product_sales,
            year(order_date) as order_year,
            weekofyear(order_date) as order_week,
            weekday(order_date) as order_weekday
        from product_sales
        -- Optional: Add WHERE conditions here
        ;
-- IMPORTANT: Add the relevant indexes to your temp table. This will
-- speed up things
alter table temp_product_sales
    add index odt(order_date),
    add index oid(order_id),
    add index pid(product_id),
    add index sku(sku_code),
    add index oy(order_year),
    add index ow(order_week),
    add index owd(order_weekday);
-- Finally, execute your final query:
select product_id, sku_code, order_year, order_week
     , sum(case order_weekday when 0 then units_sold else 0 end) as monday_units
     , sum(case order_weekday when 1 then units_sold else 0 end) as tuesday_units
     , sum(case order_weekday when 2 then units_sold else 0 end) as wednesday_units
     , sum(case order_weekday when 3 then units_sold else 0 end) as thursday_units
     , sum(case order_weekday when 4 then units_sold else 0 end) as friday_units
     , sum(case order_weekday when 5 then units_sold else 0 end) as saturday_units
     , sum(case order_weekday when 6 then units_sold else 0 end) as sunday_units
from temp_product_sales
-- Example of WHERE condition:
where order_year = 2015 and order_week = 51
group by product_id, sku_code, order_year, order_week;

请记住:临时表仅对创建它们的连接可见,并在连接关闭或终止后被删除。

希望对你有帮助

【讨论】:

  • 这确实有帮助。我从来没有使用过临时表,我会试一试。我不能使用您的第一个解决方案(将感兴趣的星期和年份放在 where 子句中)的原因是因为实际上我希望同时进行更多这种性质的计算(从一周到今天,一个月到日期,年初至今,一生),我打算让他们都吐在一行上。我会试试总和(情况何时)。我没有想到这一点。谢谢!
  • @jmo 乐于助人!顺便说一句,如果您觉得这个答案有用,请给它投票(如果它解决了您的问题,请考虑接受它;))
  • 我知道是什么阻止了我的代码因为你的代码而工作(即使我不能使用带有 where 子句的整体集)。 Sum() 需要在案例之外进行。哎呀。谢谢你,是的,我会支持你的回复。
  • @jmo 太棒了!我很高兴你想出了你的解决方案。如果您发现查询速度很慢,请考虑使用临时表作为中间步骤的“分而治之”策略
猜你喜欢
  • 2014-12-20
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 1970-01-01
  • 2019-10-14
相关资源
最近更新 更多