我如何使用 SQL 知道一个月中剩余的星期一、星期二、星期三、...和星期日的数量?
How can I know the number of remaining mondays, tuesdays, wednesdays, ..., and sundays in a month using SQL?
我想更新具有日期列的行的值,并且我想在该月生成 RemainingMondays、RemainingTuesdays 等的列值。
例如,如果我有 2019-03-20(2019 年 3 月 20 日),我需要用下一列值更新该行。剩余星期一 -> 2,剩余星期二 -> 1,剩余星期三 -> 1,剩余星期四 -> 2,剩余星期五 -> 2,剩余星期六 -> 2,剩余星期日 -> 2,(如你所见)我不想计算工作日在那一天(这意味着在该月的最后一天,所有列值的值为 0)。如何在 SQL 中执行此操作?
我用 MySQL 测试了这个解决方案,但它应该适用于任何 SQL 引擎。
测试数据:
CREATE TABLE test_date (
date date NOT NULL
);
INSERT INTO test_date VALUES
('2019-03-01'),
('2019-03-20'),
('2019-03-21'),
('2019-03-22'),
('2019-03-23'),
('2019-03-24'),
('2019-03-25'),
('2019-03-26');
获取数据的查询:
SELECT
td2.date,
/*
To calculate remaining of a weekday, you can then use this formula:
if desired_week_day_number > week_day_number
and desired_week_day_number <= (week_day_number + remaining_days_after_weeks):
remaining_weeks + 1
elseif desired_week_day_number <= (week_day_number + remaining_days_after_weeks - 7):
remaining_weeks + 1
else remaining_weeks
*/
CASE WHEN (1 > td2.week_day_number AND 1 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 1 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_sundays,
CASE WHEN (2 > td2.week_day_number AND 2 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 2 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_mondays,
CASE WHEN (3 > td2.week_day_number AND 3 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 3 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_tuesdays,
CASE WHEN (4 > td2.week_day_number AND 4 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 4 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_wednesdays,
CASE WHEN (5 > td2.week_day_number AND 5 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 5 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_thursdays,
CASE WHEN (6 > td2.week_day_number AND 6 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 6 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_fridays,
CASE WHEN (7 > td2.week_day_number AND 7 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 7 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_saturdays,
td2.*
FROM (
SELECT
td.date,
day(td.date) day_number,
dayofweek(td.date) week_day_number,
dayname(td.date) week_day_name,
day(last_day(td.date)) nb_month_days,
day(last_day(td.date)) - day(td.date) remaining_days,
floor((day(last_day(td.date)) - day(td.date)) / 7) remaining_weeks,
day(last_day(td.date)) - day(td.date) -
floor((day(last_day(td.date)) - day(td.date)) / 7) * 7 remaining_days_after_weeks
FROM test_date td
) AS td2
ORDER BY td2.date;
您可以相应地在更新语句中插入完全相同的内容。
当然可以shorter/simpler如果你把工作日放在子查询/sub-table中,避免为一周中的每一天重复公式,但我现在让你做这个练习。 ;-) 这项工作的难点主要在于弄清楚如何计算给定工作日的剩余时间。
我想更新具有日期列的行的值,并且我想在该月生成 RemainingMondays、RemainingTuesdays 等的列值。 例如,如果我有 2019-03-20(2019 年 3 月 20 日),我需要用下一列值更新该行。剩余星期一 -> 2,剩余星期二 -> 1,剩余星期三 -> 1,剩余星期四 -> 2,剩余星期五 -> 2,剩余星期六 -> 2,剩余星期日 -> 2,(如你所见)我不想计算工作日在那一天(这意味着在该月的最后一天,所有列值的值为 0)。如何在 SQL 中执行此操作?
我用 MySQL 测试了这个解决方案,但它应该适用于任何 SQL 引擎。
测试数据:
CREATE TABLE test_date (
date date NOT NULL
);
INSERT INTO test_date VALUES
('2019-03-01'),
('2019-03-20'),
('2019-03-21'),
('2019-03-22'),
('2019-03-23'),
('2019-03-24'),
('2019-03-25'),
('2019-03-26');
获取数据的查询:
SELECT
td2.date,
/*
To calculate remaining of a weekday, you can then use this formula:
if desired_week_day_number > week_day_number
and desired_week_day_number <= (week_day_number + remaining_days_after_weeks):
remaining_weeks + 1
elseif desired_week_day_number <= (week_day_number + remaining_days_after_weeks - 7):
remaining_weeks + 1
else remaining_weeks
*/
CASE WHEN (1 > td2.week_day_number AND 1 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 1 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_sundays,
CASE WHEN (2 > td2.week_day_number AND 2 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 2 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_mondays,
CASE WHEN (3 > td2.week_day_number AND 3 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 3 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_tuesdays,
CASE WHEN (4 > td2.week_day_number AND 4 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 4 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_wednesdays,
CASE WHEN (5 > td2.week_day_number AND 5 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 5 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_thursdays,
CASE WHEN (6 > td2.week_day_number AND 6 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 6 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_fridays,
CASE WHEN (7 > td2.week_day_number AND 7 <= (td2.week_day_number + td2.remaining_days_after_weeks))
OR 7 <= (td2.week_day_number + td2.remaining_days_after_weeks - 7)
THEN td2.remaining_weeks + 1
ELSE td2.remaining_weeks
END remaining_saturdays,
td2.*
FROM (
SELECT
td.date,
day(td.date) day_number,
dayofweek(td.date) week_day_number,
dayname(td.date) week_day_name,
day(last_day(td.date)) nb_month_days,
day(last_day(td.date)) - day(td.date) remaining_days,
floor((day(last_day(td.date)) - day(td.date)) / 7) remaining_weeks,
day(last_day(td.date)) - day(td.date) -
floor((day(last_day(td.date)) - day(td.date)) / 7) * 7 remaining_days_after_weeks
FROM test_date td
) AS td2
ORDER BY td2.date;
您可以相应地在更新语句中插入完全相同的内容。
当然可以shorter/simpler如果你把工作日放在子查询/sub-table中,避免为一周中的每一天重复公式,但我现在让你做这个练习。 ;-) 这项工作的难点主要在于弄清楚如何计算给定工作日的剩余时间。