如何使用日期范围计算只有 "day of week" 的值的总和?
How to calculate sum of a value with only "day of week" using a date-range?
我有2个table就是
- 项目 table 包含 item_id、store_id、offer_start_Date 和 offer_end_date
的详细信息
- 商店 table 有 store_id、day_of_week、store_hours
两个table的结构如下-
1) Item_Table :
Store ID
Item ID
offer_start_Date
offer_end_date
NY0001
FMC0001
2021-10-30
2021-11-04
NY0001
FMC0002
2021-11-08
Null
NY0002
FMC0003
2021-11-02
2021-11-02
NY0002
FMC0004
2021-09-01
2021-10-10
2) 存储 Table :
Store ID
Day of Week
store Hours
NY0001
Monday
12
NY0001
Tuesday
12
NY0001
Wednesday
12
NY0001
Thursday
12
NY0001
Friday
0
NY0001
Saturday
14
NY0001
Sunday
0
NY0002
Monday
8
NY0002
Tuesday
8
NY0002
Wednesday
8
NY0002
Thursday
8
NY0002
Friday
8
NY0002
Saturday
8
NY0002
Sunday
8
需要确定在给定日期范围内该商品在商店中的可用时间。
假设我们需要找到 item_id 在“2021-11-01”和“2021-11-10”之间的总可用小时数。预期结果如下(当offer_end_date不可用时按今天计算)-
Store ID
Item ID
offer_start_Date
offer_end_date
Total_available_hours
NY0001
FMC0001
2021-10-30
2021-11-04
48
NY0001
FMC0002
2021-11-08
Null
36
NY0002
FMC0003
2021-11-02
2021-11-02
8
NY0002
FMC0004
2021-09-01
2021-10-10
0
解释:
- FMC0001 - 营业时间仅从“2021-11-01”到“2021-11-04”(4 整天)
- FMC0002 - 仅在“2021-11-07”和“2021-11-10”之间可用(周日至周三)
- FMC0003 - 一整天可用的时间
- FMC0004 - 超出查询日期范围
这里有一个方法可以做到这一点
create table item_table(store_id varchar(10),item_id varchar(50),offer_start_date date,offer_end_date date);
insert into item_table
select 'NY0001','FMC0001','2021-10-30','2021-11-04' union all
select 'NY0001','FMC0002','2021-11-08',Null union all
select 'NY0002','FMC0003','2021-11-02','2021-11-02' union all
select 'NY0002','FMC0004','2021-09-01','2021-10-10';
create table store_table(store_id varchar(10),day_of_week varchar(50),store_hours int);
insert into store_table
select 'NY0001','Monday', 12 union all
select 'NY0001','Tuesday', 12 union all
select 'NY0001','Wednesday', 12 union all
select 'NY0001','Thursday', 12 union all
select 'NY0001','Friday', 0 union all
select 'NY0001','Saturday', 14 union all
select 'NY0001','Sunday', 0 union all
select 'NY0002','Monday', 8 union all
select 'NY0002','Tuesday', 8 union all
select 'NY0002','Wednesday', 8 union all
select 'NY0002','Thursday', 8 union all
select 'NY0002','Friday', 8 union all
select 'NY0002','Saturday', 8 union all
select 'NY0002','Sunday', 8;
with data
as (
select a.store_id
,a.item_id
,a.offer_start_date
,a.offer_end_date
,dateadd(day,m.rnk,a.offer_start_date) as days_involved
,s.day_of_week
,s.store_hours
from item_table a
cross apply (select *
from (select row_number() over(order by (select null))-1 as rnk
from master..spt_values
)x
where x.rnk<=datediff(day,offer_start_date,isnull(offer_end_date,getdate()))
)m
join store_table s
on a.store_id=s.store_id
and s.day_of_week=datename(weekday,dateadd(day,m.rnk,a.offer_start_date))
)
select store_id,item_id,offer_start_date,offer_end_date
,sum(case when days_involved between '2021-11-01' and '2021-11-10' then
store_hours
else 0
end) as total_work_hours
from data
group by store_id,item_id,offer_start_date,offer_end_date
order by store_id,item_id
+==========+=========+==================+================+==================+
| store_id | item_id | offer_start_date | offer_end_date | total_work_hours |
+==========+=========+==================+================+==================+
| NY0001 | FMC0001 | 2021-10-30 | 2021-11-04 | 48 |
+----------+---------+------------------+----------------+------------------+
| NY0001 | FMC0002 | 2021-11-08 | (null) | 36 |
+----------+---------+------------------+----------------+------------------+
| NY0002 | FMC0003 | 2021-11-02 | 2021-11-02 | 8 |
+----------+---------+------------------+----------------+------------------+
| NY0002 | FMC0004 | 2021-09-01 | 2021-10-10 | 0 |
+----------+---------+------------------+----------------+------------------+
demo
https://sqlize.online/sql/mssql2017/7f6721a9dbc954661d0c2db44c089bc4/
您可以通过为输入日期范围内的所有日期创建临时 table 来实现。
示例数据创建脚本
CREATE TABLE item_table(store_id VARCHAR(20),item_id VARCHAR(20),offer_start_date DATE,offer_end_date DATE)
INSERT INTO item_table(store_id,item_id,offer_start_date,offer_end_date)
VALUES ('NY0001','FMC0001','2021-10-30','2021-11-04'),
('NY0001','FMC0002','2021-11-08',null),
('NY0002','FMC0003','2021-11-02','2021-11-02'),
('NY0002','FMC0004','2021-09-01','2021-10-10')
CREATE TABLE store_table(store_id VARCHAR(20),day_of_week VARCHAR(20),store_hour int)
INSERT INTO store_table(store_id,day_of_week,store_hour)
VALUES ('NY0001','Monday',12),
('NY0001','Tuesday',12),
('NY0001','Wednesday',12),
('NY0001','Thursday',12),
('NY0001','Friday',0),
('NY0001','Saturday',14),
('NY0001','Sunday',0),
('NY0002','Monday',8),
('NY0002','Tuesday',8),
('NY0002','Wednesday',8),
('NY0002','Thursday',8),
('NY0002','Friday',8),
('NY0002','Saturday',8),
('NY0002','Sunday',8)
最终脚本将是,
-- Input date range
DECLARE @StartDate DATE, @EndDate DATE;
SELECT @StartDate = '2021-11-01', @EndDate = '2021-11-10';
-- Create and populate a temporary table
DECLARE @dateList TABLE (date DATE,day_name VARCHAR(20));
WITH DateList(date,day_name) AS (SELECT @StartDate AS DATE,DATENAME(dw,@StartDate) UNION ALL SELECT DATEADD(DAY,1,date), DATENAME(dw,DATEADD(DAY,1,date)) FROM DateList WHERE date < @EndDate)
INSERT INTO @dateList(date,day_name) SELECT * FROM DateList;
-- Main query
SELECT a.store_id,item_id,offer_start_date,offer_end_date,
CASE WHEN SUM(store_hour) IS NULL THEN 0 ELSE SUM(store_hour) END AS 'total_available_hours'
FROM
(
SELECT store_id,item_id,offer_start_date,offer_end_date,date,day_name
FROM item_table i
LEFT JOIN @dateList ON((date BETWEEN offer_start_date AND offer_end_date) OR (offer_end_date IS NULL AND date>=offer_start_date AND date <= GETDATE()))
)a
LEFT JOIN
(
SELECT store_id,day_of_week,store_hour
FROM store_table
)b ON (a.store_id = b.store_id AND a.day_name=b.day_of_week)
GROUP BY a.store_id,item_id,offer_start_date,offer_end_date;
我有2个table就是
- 项目 table 包含 item_id、store_id、offer_start_Date 和 offer_end_date 的详细信息
- 商店 table 有 store_id、day_of_week、store_hours
两个table的结构如下- 1) Item_Table :
Store ID | Item ID | offer_start_Date | offer_end_date |
---|---|---|---|
NY0001 | FMC0001 | 2021-10-30 | 2021-11-04 |
NY0001 | FMC0002 | 2021-11-08 | Null |
NY0002 | FMC0003 | 2021-11-02 | 2021-11-02 |
NY0002 | FMC0004 | 2021-09-01 | 2021-10-10 |
2) 存储 Table :
Store ID | Day of Week | store Hours |
---|---|---|
NY0001 | Monday | 12 |
NY0001 | Tuesday | 12 |
NY0001 | Wednesday | 12 |
NY0001 | Thursday | 12 |
NY0001 | Friday | 0 |
NY0001 | Saturday | 14 |
NY0001 | Sunday | 0 |
NY0002 | Monday | 8 |
NY0002 | Tuesday | 8 |
NY0002 | Wednesday | 8 |
NY0002 | Thursday | 8 |
NY0002 | Friday | 8 |
NY0002 | Saturday | 8 |
NY0002 | Sunday | 8 |
需要确定在给定日期范围内该商品在商店中的可用时间。
假设我们需要找到 item_id 在“2021-11-01”和“2021-11-10”之间的总可用小时数。预期结果如下(当offer_end_date不可用时按今天计算)-
Store ID | Item ID | offer_start_Date | offer_end_date | Total_available_hours |
---|---|---|---|---|
NY0001 | FMC0001 | 2021-10-30 | 2021-11-04 | 48 |
NY0001 | FMC0002 | 2021-11-08 | Null | 36 |
NY0002 | FMC0003 | 2021-11-02 | 2021-11-02 | 8 |
NY0002 | FMC0004 | 2021-09-01 | 2021-10-10 | 0 |
解释:
- FMC0001 - 营业时间仅从“2021-11-01”到“2021-11-04”(4 整天)
- FMC0002 - 仅在“2021-11-07”和“2021-11-10”之间可用(周日至周三)
- FMC0003 - 一整天可用的时间
- FMC0004 - 超出查询日期范围
这里有一个方法可以做到这一点
create table item_table(store_id varchar(10),item_id varchar(50),offer_start_date date,offer_end_date date);
insert into item_table
select 'NY0001','FMC0001','2021-10-30','2021-11-04' union all
select 'NY0001','FMC0002','2021-11-08',Null union all
select 'NY0002','FMC0003','2021-11-02','2021-11-02' union all
select 'NY0002','FMC0004','2021-09-01','2021-10-10';
create table store_table(store_id varchar(10),day_of_week varchar(50),store_hours int);
insert into store_table
select 'NY0001','Monday', 12 union all
select 'NY0001','Tuesday', 12 union all
select 'NY0001','Wednesday', 12 union all
select 'NY0001','Thursday', 12 union all
select 'NY0001','Friday', 0 union all
select 'NY0001','Saturday', 14 union all
select 'NY0001','Sunday', 0 union all
select 'NY0002','Monday', 8 union all
select 'NY0002','Tuesday', 8 union all
select 'NY0002','Wednesday', 8 union all
select 'NY0002','Thursday', 8 union all
select 'NY0002','Friday', 8 union all
select 'NY0002','Saturday', 8 union all
select 'NY0002','Sunday', 8;
with data
as (
select a.store_id
,a.item_id
,a.offer_start_date
,a.offer_end_date
,dateadd(day,m.rnk,a.offer_start_date) as days_involved
,s.day_of_week
,s.store_hours
from item_table a
cross apply (select *
from (select row_number() over(order by (select null))-1 as rnk
from master..spt_values
)x
where x.rnk<=datediff(day,offer_start_date,isnull(offer_end_date,getdate()))
)m
join store_table s
on a.store_id=s.store_id
and s.day_of_week=datename(weekday,dateadd(day,m.rnk,a.offer_start_date))
)
select store_id,item_id,offer_start_date,offer_end_date
,sum(case when days_involved between '2021-11-01' and '2021-11-10' then
store_hours
else 0
end) as total_work_hours
from data
group by store_id,item_id,offer_start_date,offer_end_date
order by store_id,item_id
+==========+=========+==================+================+==================+
| store_id | item_id | offer_start_date | offer_end_date | total_work_hours |
+==========+=========+==================+================+==================+
| NY0001 | FMC0001 | 2021-10-30 | 2021-11-04 | 48 |
+----------+---------+------------------+----------------+------------------+
| NY0001 | FMC0002 | 2021-11-08 | (null) | 36 |
+----------+---------+------------------+----------------+------------------+
| NY0002 | FMC0003 | 2021-11-02 | 2021-11-02 | 8 |
+----------+---------+------------------+----------------+------------------+
| NY0002 | FMC0004 | 2021-09-01 | 2021-10-10 | 0 |
+----------+---------+------------------+----------------+------------------+
demo
https://sqlize.online/sql/mssql2017/7f6721a9dbc954661d0c2db44c089bc4/
您可以通过为输入日期范围内的所有日期创建临时 table 来实现。
示例数据创建脚本
CREATE TABLE item_table(store_id VARCHAR(20),item_id VARCHAR(20),offer_start_date DATE,offer_end_date DATE)
INSERT INTO item_table(store_id,item_id,offer_start_date,offer_end_date)
VALUES ('NY0001','FMC0001','2021-10-30','2021-11-04'),
('NY0001','FMC0002','2021-11-08',null),
('NY0002','FMC0003','2021-11-02','2021-11-02'),
('NY0002','FMC0004','2021-09-01','2021-10-10')
CREATE TABLE store_table(store_id VARCHAR(20),day_of_week VARCHAR(20),store_hour int)
INSERT INTO store_table(store_id,day_of_week,store_hour)
VALUES ('NY0001','Monday',12),
('NY0001','Tuesday',12),
('NY0001','Wednesday',12),
('NY0001','Thursday',12),
('NY0001','Friday',0),
('NY0001','Saturday',14),
('NY0001','Sunday',0),
('NY0002','Monday',8),
('NY0002','Tuesday',8),
('NY0002','Wednesday',8),
('NY0002','Thursday',8),
('NY0002','Friday',8),
('NY0002','Saturday',8),
('NY0002','Sunday',8)
最终脚本将是,
-- Input date range
DECLARE @StartDate DATE, @EndDate DATE;
SELECT @StartDate = '2021-11-01', @EndDate = '2021-11-10';
-- Create and populate a temporary table
DECLARE @dateList TABLE (date DATE,day_name VARCHAR(20));
WITH DateList(date,day_name) AS (SELECT @StartDate AS DATE,DATENAME(dw,@StartDate) UNION ALL SELECT DATEADD(DAY,1,date), DATENAME(dw,DATEADD(DAY,1,date)) FROM DateList WHERE date < @EndDate)
INSERT INTO @dateList(date,day_name) SELECT * FROM DateList;
-- Main query
SELECT a.store_id,item_id,offer_start_date,offer_end_date,
CASE WHEN SUM(store_hour) IS NULL THEN 0 ELSE SUM(store_hour) END AS 'total_available_hours'
FROM
(
SELECT store_id,item_id,offer_start_date,offer_end_date,date,day_name
FROM item_table i
LEFT JOIN @dateList ON((date BETWEEN offer_start_date AND offer_end_date) OR (offer_end_date IS NULL AND date>=offer_start_date AND date <= GETDATE()))
)a
LEFT JOIN
(
SELECT store_id,day_of_week,store_hour
FROM store_table
)b ON (a.store_id = b.store_id AND a.day_name=b.day_of_week)
GROUP BY a.store_id,item_id,offer_start_date,offer_end_date;