如何从 SQL 中的日期范围计数中排除两个不同国家的节假日

问题描述 投票:0回答:1

我有一张看起来像这样的桌子:

优惠

id 子_id 交易开始 交易结束 国家_A 国家_B
10 1 2024-10-21 2024-10-25 美国 俄罗斯
10 2 2024-10-21 2024-10-25 美国 中国
10 3 2024-10-21 2024-10-24 俄罗斯 美国
11 1 2024-10-21 2024-10-25 中国 俄罗斯
11 2 2024-10-21 2024-10-23 中国 美国

我需要计算每行的交易期限,但不包括两个国家/地区的周末和节假日。

为此,我有一张所有国家/地区所有日期的周末和假期表,如下所示。

假期

1 - 工作日

2 - 假期或周末

日期 国家 日类型
2024-10-21 俄罗斯 2
2024-10-21 中国 1
2024-10-21 美国 1
2024-10-22 俄罗斯 1
2024-10-22 中国 2
2024-10-22 美国 1
2024-10-23 俄罗斯 1
2024-10-23 中国 1
2024-10-23 美国 2
2024-10-24 俄罗斯 2
2024-10-24 中国 1
2024-10-24 美国 2

我正在使用 SQL Impala 方言并尝试像这样的查询,但没有成功。此外,这种方法没有考虑重叠日期。最后,我无法在工作中使用 UDF。

SELECT id,
       sub_id,
       deal_start,
       deal_end,
       country_A,
       country_B,
       DATEDIFF(d.deal_end, d.deal_start) AS dirty_term,
       COUNT(hA.date) AS country_A_hd,
       COUNT(hB.date) AS country_B_hd,
       (DATEDIFF(d.deal_end, d.deal_start) - GREATEST(COUNT(hA.date), COUNT(hA.date))
FROM deals AS d
LEFT JOIN holydays AS hA ON hA.country=d.country_A AND hA.date BETWEEN d.deal_start AND d.deal_end AND hA.day_type = 2
LEFT JOIN holydays AS hB ON hB.country=d.country_B AND hB.date BETWEEN d.deal_start AND d.deal_end AND hB.day_type = 2
GROUP BY id,
       sub_id,
       deal_start,
       deal_end,
       country_A,
       country_B

理想情况下我需要得到这个结果:

id 子_id 交易开始 交易结束 国家_A 国家_B 日期差异 总计_AB_hd 真实术语
10 1 2024-10-21 2024-10-25 美国 俄罗斯 4 3 1
10 2 2024-10-21 2024-10-25 美国 中国 4 3 1
10 3 2024-10-21 2024-10-24 俄罗斯 美国 3 2 1
11 1 2024-10-21 2024-10-25 中国 俄罗斯 4 3 1
11 2 2024-10-21 2024-10-23 中国 美国 2 1 1

使用以下逻辑

总计_AB_hd

2024-10-21 2024-10-22 2024-10-23 2024-10-24
2 2 1 2

国家_A

1 2 1 2

国家_B

2 1 1 2

请帮忙。

非常感谢您抽出时间。

sql impala
1个回答
0
投票

在对 MySQL 设置进行一些修改之后,我想我找到了解决方案。希望您在移植到“SQL Impala 方言”设置时不会遇到太多麻烦。

要计算两个国家/地区的假期,它使用子查询,并在日期列上的假期表和自身之间进行联接。这会产生一个表格,其中特定日期的每个国家/地区都与同一日期的所有其他国家/地区相匹配。

SELECT * FROM holidays AS hA
JOIN holidays AS hB
ON hA.date = hB.date;
+------------+---------+----------+------------+---------+----------+
| date       | country | day_type | date       | country | day_type |
+------------+---------+----------+------------+---------+----------+
| 2024-10-21 | RUS     |        2 | 2024-10-21 | RUS     |        2 |
| 2024-10-21 | CHN     |        1 | 2024-10-21 | RUS     |        2 |
| 2024-10-21 | USA     |        1 | 2024-10-21 | RUS     |        2 |
| 2024-10-21 | RUS     |        2 | 2024-10-21 | CHN     |        1 |
| 2024-10-21 | CHN     |        1 | 2024-10-21 | CHN     |        1 |
| 2024-10-21 | USA     |        1 | 2024-10-21 | CHN     |        1 |
| 2024-10-21 | RUS     |        2 | 2024-10-21 | USA     |        1 |
| 2024-10-21 | CHN     |        1 | 2024-10-21 | USA     |        1 |
| 2024-10-21 | USA     |        1 | 2024-10-21 | USA     |        1 |
| 2024-10-22 | RUS     |        1 | 2024-10-22 | RUS     |        1 |
| 2024-10-22 | CHN     |        2 | 2024-10-22 | RUS     |        1 |

然后可以按 day_type 设置为 2 的国家/地区之一进行过滤。最后,对结果行进行计数。

SELECT id,
    sub_id,
    deal_start,
    deal_end,
    country_A,
    country_B,
    @datediff := DATEDIFF(d.deal_end, d.deal_start) AS datediff,
    @total_AB_hd := (
        SELECT COUNT(*) 
        FROM holidays AS hA
        JOIN holidays AS hB
        ON hA.date = hB.date
        WHERE
            hA.country = d.country_A AND hB.country = d.country_B AND
            hA.date BETWEEN d.deal_start AND d.deal_end AND
            (hA.day_type = 2 OR hB.day_type = 2)
    ) AS total_AB_hd,
    (@datediff - @total_AB_hd) AS real_term
FROM deals AS d;
+------+--------+------------+------------+-----------+-----------+----------+-------------+-----------+
| id   | sub_id | deal_start | deal_end   | country_A | country_B | datediff | total_AB_hd | real_term |
+------+--------+------------+------------+-----------+-----------+----------+-------------+-----------+
|   10 |      1 | 2024-10-21 | 2024-10-25 | USA       | RUS       |        4 |           3 |         1 |
|   10 |      2 | 2024-10-21 | 2024-10-25 | USA       | CHN       |        4 |           3 |         1 |
|   10 |      3 | 2024-10-21 | 2024-10-24 | RUS       | USA       |        3 |           3 |         0 |
|   11 |      1 | 2024-10-21 | 2024-10-25 | CHN       | RUS       |        4 |           3 |         1 |
|   11 |      2 | 2024-10-21 | 2024-10-23 | CHN       | USA       |        2 |           2 |         0 |
+------+--------+------------+------------+-----------+-----------+----------+-------------+-----------+

注意:我希望这些结果是您想要的结果,因为您在问题中提到的结果与我的不同。

© www.soinside.com 2019 - 2024. All rights reserved.