繁体   English   中英

根据 SQL 中的另一列获取记录的 COUNT/SUM

[英]Get COUNT/SUM of records based on another column in SQL

如何根据另一列(类型:每周或每年)获取行数/总和(COUNT () 或 SUM ())? 我有两张桌子:

  1. 商店:
ID 姓名 类型
1个 商店 1 每周
2个 店铺 2 每年
3个 商店 3 每周
4个 商店 4 每周
  1. 命令:
ID 店铺编号 订购日期 数量
1个 1个 2022-01-31 2个
2个 1个 2022-12-31 5*
3个 2个 2022-01-28 30*
4个 2个 2022-06-30 50*
5个 2个 2022-12-31 70*
6个 3个 2022-06-15 8个
7 3个 2022-12-27 9*
8个 3个 2022-12-31 3*

a) 如果我超过日期范围(按周2022-12-26 ~ 2023-01-01 ),预期结果应如下所示:

ID 姓名 订单数 总数量
1个 商店 1 1个 5个
2个 店铺 2 3个 150(店铺类型为“年”时按年份求和:30+50+70)
3个 商店 3 2个 12(所选周的总和:9+3)
4个 商店 4 0 0

如果Store typeYearly那么所有订单将根据StoreIdOrderDateyear进行汇总,如果是Weekly然后基于 StoreId 和选择的 OrderDate。

b) 我尝试在 SELECT 语句中使用CASE ,但没有成功,这是我的部分代码:

SELECT s.Id,
       s.Name,
       COUNT(o.Id) AS 'Count of orders',
       sum(o.Qty) AS 'Total Qty'
  FROM Stores AS s
  LEFT JOIN Orders AS o
    ON o.StoreId = s.id
   AND (OrderDate >= '2022-12-26' AND OrderDate <= '2023-01-01')
 GROUP BY s.Id, OrderDate
 ORDER BY OrderDate DESC

您可以按如下方式使用条件聚合:

SELECT s.Id,
       s.Name,
       COUNT(CASE
               WHEN s.Type = 'Yearly' THEN
                o.Id
               ELSE
                CASE
                  WHEN OrderDate >= '2022-12-26' AND OrderDate <= '2023-01-01' THEN
                   o.Id
                END
             END) As 'Count of orders',
       SUM(CASE
             WHEN s.Type = 'Yearly' THEN
              o.Qty
             ELSE
              CASE
                WHEN OrderDate >= '2022-12-26' AND OrderDate <= '2023-01-01' THEN
                 o.Qty
                ELSE
                 0
              END
           END) AS 'Total Qty'
  FROM Stores AS s
  LEFT JOIN Orders AS o
    ON o.StoreId = s.id
 GROUP BY s.Id, s.Name
 ORDER BY MAX(OrderDate) DESC

演示

你可以这样做。 请注意, type是 MySQL 中的关键字。

SELECT s.id,
       s.name,
       s.type,
       COUNT(s.name) AS total_count,
       SUM(o.qty) AS total_qty
  FROM stores s
  LEFT JOIN orders o
    ON s.id = o.storeid
 WHERE (o.orderdate >= '2022-12-26' AND o.orderDate <= '2023-01-01' 
   AND  s.type = 'Weekly')
    OR  s.type = 'Yearly'
 GROUP BY s.id, s.name, s.type

根据描述,计算count(Orders.Id)sum(Orders.Qty)

  1. Stores.Type = 'Weekly': Orders.OrderDate 在@start_date 和@end_date 之间

  2. Stores.Type = 'Yearly': @start_date 年份的 Orders.OrderDate(...所有订单将根据 StoreId 和 OrderDate 年份进行汇总。)

因此,第一步是让where子句过滤掉订单,然后聚合到Store.Id级别。 然后,第二步是从Stores表左连接到第一步的结果,以便报告指定日期范围内没有销售的商店。

set @start_date = '2022-12-26', @end_date = '2023-01-01';

with cte_store_sales as (
select s.Id,
       count(o.Id) as order_count,
       sum(o.Qty)  as total_qty
  from stores s
  left 
  join orders o
    on s.Id = o.StoreId
 where (s.type = 'Weekly' and o.OrderDate between @start_date and @end_date)
    or (s.type = 'Yearly' and o.OrderDate between makedate(year(@start_date),1)
                                              and date_sub(date_add(makedate(year(@start_date),1), interval 1 year), interval 1 day))
 group by s.Id)
select s.Id,
       s.Name,
       coalesce(ss.order_count, 0) as "Count of Orders",
       coalesce(ss.total_qty, 0)   as "Total Qty"
  from stores s
  left
  join cte_store_sales ss
    on s.Id = ss.Id
 order by s.Id;

Output:

Id|Name   |Count of Orders|Total Qty|
--+-------+---------------+---------+
 1|Store 1|              1|        5|
 2|Store 2|              3|      150| <-- Store sales in year 2022
 3|Store 3|              2|       12|
 4|Store 4|              0|        0| <-- Report stores without sales 

首先,我们要提取符合orderdate表条件的原始数据,以供后面聚合使用。 注意,这里我将日期范围视为包含在内 因此,如果类型为年,则2022-12-26 ~ 2023-01-01 应为2022 年和2023 年。

    select s.id id, name,
        (case when type='weekly' and orderdate between '2022-12-26' and '2023-01-01' then qty
         when type='yearly' and year(orderdate) between year('2022-12-26') and year('2023-01-01') then qty
        end) as qt
    from Stores s
    left join Orders o
    on s.id=o.storeid;
-- result set:
# id, name, qt
1, Store 1, 5
2, Store 2, 30
2, Store 2, 50
2, Store 2, 70
3, Store 3, 
3, Store 3, 9
3, Store 3, 3
4, Store 4, 

rest 用于使用派生表进行汇总工作。 注意:由于列name不在group by列表中,但它实际上对于特定的 storeid 是唯一的,我们可以使用 any_value function 来绕过可能由于SQL_MODE系统变量而强制执行的限制。

select id,any_value(name) as'Name',count(qt) as 'Count of orders', ifnull(sum(qt),0) as 'Total Qty'
from
    (select s.id id, name,
        (case when type='weekly' and orderdate between '2022-12-26' and '2023-01-01' then qty
         when type='yearly' and year(orderdate) between year('2022-12-26') and year('2023-01-01') then qty
        end) as qt
    from Stores s
    left join Orders o
    on s.id=o.storeid) tb
group by id
order by id
;
-- result set:
# id, Name, Count of orders, Total Qty
1, Store 1, 1, 5
2, Store 2, 3, 150
3, Store 3, 2, 12
4, Store 4, 0, 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM