有联邦制国家的学校假期的差距和岛屿

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

periods表包含学生休学期间的数据。 locations表包含国家和联邦州。我想列出从“ 2019-12-15”到“ 2020-01-15”的所有时间段,并累积每个岛屿的休息日总数。

要收集数据,我必须搜索位置1和位置2的所有时段。周末是与国家相关的时段,而学校假期与联邦州相关。

数据

所有数据都存储在PostgreSQL数据库中。我无法控制表格结构。

位置

|----|-------------------|------------------|------------|
| id |       name        | is_federal_state | is_country |
|----|-------------------|------------------|------------|
|  1 | Deutschland       | f                | t          |
|  2 | Baden-Württemberg | t                | f          |
|----|-------------------|------------------|------------| 

“ Deutschland”是德国的国家。 “巴登-符腾堡州”是德国的联邦州。

期间

|-----|------------|------------|-------------|
| id  | starts_on  |  ends_on   | location_id |
|-----|------------|------------|-------------|
| 678 | 2019-12-21 | 2019-12-22 |           1 |
| 534 | 2019-12-23 | 2020-01-04 |           2 |
| 679 | 2019-12-28 | 2019-12-29 |           1 |
|   9 | 2020-01-01 | 2020-01-01 |           2 |
| 776 | 2020-01-04 | 2020-01-05 |           1 |
|   7 | 2020-01-06 | 2020-01-06 |           2 |
| 777 | 2020-01-11 | 2020-01-12 |           1 |
|-----|------------|------------|-------------|

periods表存储有关学生不必上学的时间段的信息。 678、679、776和777是与国家相关联的周末(编号1)。另一个是与联邦州(id 2)相关的学校假期或公共假期。

查询

Find rows with adjourning date ranges and accumulate their durations的帮助下,我发现这是一个空白和孤立的问题。但是我不明白如何正确使用它。这就是我所拥有的:

SELECT
  p.*,
  (
      Max(ends_on) OVER (PARTITION BY location_id) - Min(starts_on) OVER (PARTITION BY location_id) 
  )
  + 1 AS duration  
FROM
  (
      SELECT
        p.*,
        Count(*) FILTER (
      WHERE
        prev_eo < starts_on - INTERVAL '1 day') OVER (PARTITION BY location_id 
      ORDER BY
        starts_on) AS grp 
      FROM
        (
            SELECT
              id,
              starts_on,
              ends_on,
              location_id,
              lag(ends_on) OVER (PARTITION BY location_id 
            ORDER BY
(starts_on)) AS prev_eo 
            FROM
              periods 
            WHERE
              location_id IN 
              (
                  1,
                  2
              )
              AND starts_on > '2019-12-15' 
              AND starts_on < '2020-01-15' 
        )
        p 
  )
  p;

结果

|-----|------------|------------|-------------|-----|----------|
| id  | starts_on  |  ends_on   | location_id | grp | duration |
|-----|------------|------------|-------------|-----|----------|
| 678 | 2019-12-21 | 2019-12-22 |           1 |   0 |       23 |
| 679 | 2019-12-28 | 2019-12-29 |           1 |   1 |       23 |
| 776 | 2020-01-04 | 2020-01-05 |           1 |   2 |       23 |
| 777 | 2020-01-11 | 2020-01-12 |           1 |   3 |       23 |
| 534 | 2019-12-23 | 2020-01-04 |           2 |   0 |       15 |
|   9 | 2020-01-01 | 2020-01-01 |           2 |   0 |       15 |
|   7 | 2020-01-06 | 2020-01-06 |           2 |   1 |       15 |
|-----|------------|------------|-------------|-----|----------|

此结果存在问题:

  • 此结果假设位置ID 1的所有周末都是一个大岛。但事实并非如此。除了一个周末外,所有假期都属于圣诞节假期岛。
  • ID 2的实际圣诞节假期的持续时间为15,其中应包括ID 678,该ID应该是圣诞节岛的一部分(加上该期间的其他周末)。

我想要的结果

|-----|------------|------------|-------------|----------|
| id  | starts_on  |  ends_on   | location_id | duration |
|-----|------------|------------|-------------|----------|
| 678 | 2019-12-21 | 2019-12-22 |           1 |       15 |
| 679 | 2019-12-28 | 2019-12-29 |           1 |       15 |
| 776 | 2020-01-04 | 2020-01-05 |           1 |       15 |
| 777 | 2020-01-11 | 2020-01-12 |           1 |        2 |
| 534 | 2019-12-23 | 2020-01-04 |           2 |       15 |
|   9 | 2020-01-01 | 2020-01-01 |           2 |       15 |
|   7 | 2020-01-06 | 2020-01-06 |           2 |       15 |
|-----|------------|------------|-------------|----------|

哪个查询将在此结果中生成?

游乐场

所有数据和查询:https://rextester.com/FEL57082

sql postgresql gaps-and-islands
1个回答
1
投票
© www.soinside.com 2019 - 2024. All rights reserved.