DATE_DIFF 但只计算工作日
DATE_DIFF but only counting business days
我有一个相当简单的查询;它看起来是这样的:
SELECT
order_date,
pickup_date,
DATE_DIFF(pickup_date,order_date, day) order_to_pickup
FROM
`orders.table`
唯一的问题是,我需要计算工作日的日期差异,而不是所有天数。
所以不用上面的查询 returning:
+------------+-------------+-----------------+
| order_date | pickup_date | order_to_pickup |
+------------+-------------+-----------------+
| 3/29/19 | 4/3/19 | 5 |
| 3/29/19 | 4/2/19 | 4 |
+------------+-------------+-----------------+
我想要 return:
+------------+-------------+-----------------+
| order_date | pickup_date | order_to_pickup |
+------------+-------------+-----------------+
| 3/29/19 | 4/3/19 | 2 |
| 3/29/19 | 4/2/19 | 3 |
+------------+-------------+-----------------+
我认为如果你考虑两个日期之间的周数,会有一个聪明的解决方案,但同时这里有一个蛮力方法:
CREATE TEMP FUNCTION BusinessDateDiff(start_date DATE, end_date DATE) AS (
(SELECT COUNTIF(MOD(EXTRACT(DAYOFWEEK FROM date), 7) > 1)
FROM UNNEST(GENERATE_DATE_ARRAY(
start_date, DATE_SUB(end_date, INTERVAL 1 DAY))) AS date)
);
根据您的意见,我得到:
CREATE TEMP FUNCTION BusinessDateDiff(start_date DATE, end_date DATE) AS (
(SELECT COUNTIF(MOD(EXTRACT(DAYOFWEEK FROM date), 7) > 1)
FROM UNNEST(GENERATE_DATE_ARRAY(
start_date, DATE_SUB(end_date, INTERVAL 1 DAY))) AS date)
);
WITH OrdersTable AS (
SELECT
DATE '2019-03-29' AS order_date,
DATE '2019-04-03' AS pickup_date UNION ALL
SELECT
'2019-03-29',
'2019-04-02'
)
SELECT
order_date,
pickup_date,
BusinessDateDiff(order_date, pickup_date) AS order_to_pickup
FROM OrdersTable
ORDER BY pickup_date
+------------+-------------+-----------------+
| order_date | pickup_date | order_to_pickup |
+------------+-------------+-----------------+
| 2019-03-29 | 2019-04-02 | 2 |
| 2019-03-29 | 2019-04-03 | 3 |
+------------+-------------+-----------------+
这是一种工作方法,用于根据 Looker Discourse 社区中的工作计算日期之间的工作日 here。原始示例适用于 Redshift,因此我在下面针对 BigQuery 对其进行了调整。
SELECT
CAST(-1*(DATE_DIFF(DATE '2019-01-01', DATE '2019-01-31', DAY) - ((FLOOR(DATE_DIFF(DATE '2019-01-01', DATE '2019-01-31', DAY) / 7) * 2) +
CASE
WHEN EXTRACT(DAYOFWEEK FROM DATE '2019-01-01') - EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') IN (1, 2, 3, 4, 5) AND EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') != 0 THEN 2
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM DATE '2019-01-01') != 0 AND EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') = 0 THEN 1
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM DATE '2019-01-01') = 0 AND EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') != 0 THEN 1
ELSE 0 END)) AS int64) AS weekdays
将此应用于您的数据集,我们得到:
SELECT
order_date,
pickup_date,
CAST(-1*(DATE_DIFF(order_date, pickup_date, DAY) - ((FLOOR(DATE_DIFF(order_date, pickup_date, DAY) / 7) * 2) +
CASE
WHEN EXTRACT(DAYOFWEEK FROM order_date) - EXTRACT(DAYOFWEEK FROM pickup_date) IN (1, 2, 3, 4, 5) AND EXTRACT(DAYOFWEEK FROM pickup_date) != 0 THEN 2
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM order_date') != 0 AND EXTRACT(DAYOFWEEK FROM pickup_date) = 0 THEN 1
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM order_date) = 0 AND EXTRACT(DAYOFWEEK FROM pickup_date) != 0 THEN 1
ELSE 0 END)) AS int64) AS weekdays
FROM
`orders.table`
这应该是@Elliott Brossard 提到的简化的非暴力解决方案:
select
order_date,
pickup_date,
case
when date_diff(pickup_date, order_date, week) > 0
then date_diff(pickup_date, order_date, day) - (date_diff(pickup_date, order_date, week) * 2)
else
date_diff(pickup_date, order_date, day)
end
from `orders.table`
另一种解决方案。删除周末天数:
SELECT
order_date,
pickup_date,
date_diff(pickup_date, order_date, day)
- date_diff(pickup_date, order_date, WEEK(SUNDAY))
- date_diff(pickup_date, order_date, WEEK(SATURDAY)) as order_to_pickup
FROM `orders.table`
我有一个相当简单的查询;它看起来是这样的:
SELECT
order_date,
pickup_date,
DATE_DIFF(pickup_date,order_date, day) order_to_pickup
FROM
`orders.table`
唯一的问题是,我需要计算工作日的日期差异,而不是所有天数。
所以不用上面的查询 returning:
+------------+-------------+-----------------+
| order_date | pickup_date | order_to_pickup |
+------------+-------------+-----------------+
| 3/29/19 | 4/3/19 | 5 |
| 3/29/19 | 4/2/19 | 4 |
+------------+-------------+-----------------+
我想要 return:
+------------+-------------+-----------------+
| order_date | pickup_date | order_to_pickup |
+------------+-------------+-----------------+
| 3/29/19 | 4/3/19 | 2 |
| 3/29/19 | 4/2/19 | 3 |
+------------+-------------+-----------------+
我认为如果你考虑两个日期之间的周数,会有一个聪明的解决方案,但同时这里有一个蛮力方法:
CREATE TEMP FUNCTION BusinessDateDiff(start_date DATE, end_date DATE) AS (
(SELECT COUNTIF(MOD(EXTRACT(DAYOFWEEK FROM date), 7) > 1)
FROM UNNEST(GENERATE_DATE_ARRAY(
start_date, DATE_SUB(end_date, INTERVAL 1 DAY))) AS date)
);
根据您的意见,我得到:
CREATE TEMP FUNCTION BusinessDateDiff(start_date DATE, end_date DATE) AS (
(SELECT COUNTIF(MOD(EXTRACT(DAYOFWEEK FROM date), 7) > 1)
FROM UNNEST(GENERATE_DATE_ARRAY(
start_date, DATE_SUB(end_date, INTERVAL 1 DAY))) AS date)
);
WITH OrdersTable AS (
SELECT
DATE '2019-03-29' AS order_date,
DATE '2019-04-03' AS pickup_date UNION ALL
SELECT
'2019-03-29',
'2019-04-02'
)
SELECT
order_date,
pickup_date,
BusinessDateDiff(order_date, pickup_date) AS order_to_pickup
FROM OrdersTable
ORDER BY pickup_date
+------------+-------------+-----------------+
| order_date | pickup_date | order_to_pickup |
+------------+-------------+-----------------+
| 2019-03-29 | 2019-04-02 | 2 |
| 2019-03-29 | 2019-04-03 | 3 |
+------------+-------------+-----------------+
这是一种工作方法,用于根据 Looker Discourse 社区中的工作计算日期之间的工作日 here。原始示例适用于 Redshift,因此我在下面针对 BigQuery 对其进行了调整。
SELECT
CAST(-1*(DATE_DIFF(DATE '2019-01-01', DATE '2019-01-31', DAY) - ((FLOOR(DATE_DIFF(DATE '2019-01-01', DATE '2019-01-31', DAY) / 7) * 2) +
CASE
WHEN EXTRACT(DAYOFWEEK FROM DATE '2019-01-01') - EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') IN (1, 2, 3, 4, 5) AND EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') != 0 THEN 2
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM DATE '2019-01-01') != 0 AND EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') = 0 THEN 1
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM DATE '2019-01-01') = 0 AND EXTRACT(DAYOFWEEK FROM DATE '2019-01-31') != 0 THEN 1
ELSE 0 END)) AS int64) AS weekdays
将此应用于您的数据集,我们得到:
SELECT
order_date,
pickup_date,
CAST(-1*(DATE_DIFF(order_date, pickup_date, DAY) - ((FLOOR(DATE_DIFF(order_date, pickup_date, DAY) / 7) * 2) +
CASE
WHEN EXTRACT(DAYOFWEEK FROM order_date) - EXTRACT(DAYOFWEEK FROM pickup_date) IN (1, 2, 3, 4, 5) AND EXTRACT(DAYOFWEEK FROM pickup_date) != 0 THEN 2
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM order_date') != 0 AND EXTRACT(DAYOFWEEK FROM pickup_date) = 0 THEN 1
ELSE 0
END +
CASE
WHEN EXTRACT(DAYOFWEEK FROM order_date) = 0 AND EXTRACT(DAYOFWEEK FROM pickup_date) != 0 THEN 1
ELSE 0 END)) AS int64) AS weekdays
FROM
`orders.table`
这应该是@Elliott Brossard 提到的简化的非暴力解决方案:
select
order_date,
pickup_date,
case
when date_diff(pickup_date, order_date, week) > 0
then date_diff(pickup_date, order_date, day) - (date_diff(pickup_date, order_date, week) * 2)
else
date_diff(pickup_date, order_date, day)
end
from `orders.table`
另一种解决方案。删除周末天数:
SELECT
order_date,
pickup_date,
date_diff(pickup_date, order_date, day)
- date_diff(pickup_date, order_date, WEEK(SUNDAY))
- date_diff(pickup_date, order_date, WEEK(SATURDAY)) as order_to_pickup
FROM `orders.table`