简体   繁体   English

如何将“开始日期”列、“结束日期”列和带有“名称”的列变成运行日期,并将带有该名称的列用于其间的所有日期

[英]How do I turn a Start Date column, an End Date column and a column with a Name into running dates and a column with that name for all dates in between

I need help in order to turn table A我需要帮助才能转动桌子 A

DATES日期 Start_DATE开始日期 END_DATE结束日期 NAME名称
1.1.20 1.1.20 1.1.20 1.1.20 3.1.20 3.1.20 Name1姓名1
2.1.20 2.1.20
3.1.20 3.1.20
4.1.20 4.1.20
5.1.20 5.1.20 5.1.20 5.1.20 5.1.20 5.1.20 Name2名字2
6.1.20 6.1.20

into table B using SQL.使用 SQL 进入表 B。

DATES日期 NAME名称
1.1.20 1.1.20 Name1姓名1
2.1.20 2.1.20 Name1姓名1
3.1.20 3.1.20 Name1姓名1
4.1.20 4.1.20
5.1.20 5.1.20 Name2名字2
6.1.20 6.1.20

So I want 'NAME' next to all 'DATES' in the range of the 'START_DATE' and 'END_DATE' of 'NAME'所以我想在“NAME”的“START_DATE”和“END_DATE”范围内的所有“DATES”旁边添加“NAME”

I am completely lost and would appreciate your help!我完全迷路了,非常感谢您的帮助!
Thank you谢谢

I tried to group the data by START_DATE or by NAME or by END_DATE eg.我尝试按 START_DATE 或按 NAME 或按 END_DATE 对数据进行分组,例如。

count(END_Date) over (ORDER BY DATE) AS grp

and than use而不是使用

first_value(NAME) over (partition by grp order by DATE)

to fill the blanks.填补空白。 Did not work不工作

you can use cross join and then distinct to do this.您可以使用 cross join 然后使用 distinct 来执行此操作。
Pls refer to below SQL -请参考以下 SQL -

select 
distinct 
dates,
case when dates between b.Start_DATE and    b.END_DATE then b.NAME else null end as name
from tablea a 
left join ( select distinct Start_DATE, END_DATE,   NAME from tableA) b on 
case when dates between b.Start_DATE and b.END_DATE then 1 else 0 end =1

select distinct Start_DATE, END_DATE, NAME from tableA - This will give you all combination of start,end,name columns. select distinct Start_DATE, END_DATE, NAME from tableA - 这将为您提供开始、结束、名称列的所有组合。
case when dates between b.Start_DATE and b.END_DATE then 1 else 0 end =1 - this will ensure you dont have unnecessary cross joins but still some cross join will be there. case when dates between b.Start_DATE and b.END_DATE then 1 else 0 end =1 - 这将确保您没有不必要的交叉连接,但仍然会有一些交叉连接。

I did some R&D with my DB, and here are the output.我用我的数据库做了一些研发,这是 output。

我的输出

Well, basically, you need two data sets (tables, views, or CTEs):嗯,基本上,您需要两个数据集(表、视图或 CTE):

  • A list of dates, and日期列表,以及
  • A list of holiday date ranges假期日期范围列表

Fortunately, table A is both of those!幸运的是,表 A 就是这两个!

Let's do this with a CTE (Common Table Expression):让我们用 CTE(公用表表达式)来做到这一点:

WITH Calendar as (
   SELECT a.Dates as CalendarDate
   FROM   TableA a
)
SELECT  c.CalendarDate
        n.Name
FROM    Calendar c
  LEFT JOIN TableA n
    ON  c.CalendarDate between n.StartDate and n.EndDate

This won't handle the case where multiple names have overlapping date ranges, but you didn't indicate how you needed that handled.这不会处理多个名称具有重叠日期范围的情况,但您没有说明您需要如何处理。 In the above, if "Name1" and "Name2" had overlapping ranges, you would see a record for each name for each date (from Calendar ) that overlapped.在上面,如果“Name1”和“Name2”有重叠范围,您会看到重叠的每个日期(来自Calendar )的每个名称的记录。

You can use a user defined table function to carry a value through the date range that's specified in the columns:您可以使用用户定义的表 function 在列中指定的日期范围内携带一个值:

-- Sample data:
create or replace temp table T1 as 
select 
COLUMN1::date as "DATES",
COLUMN2::date as "START_DATE",
COLUMN3::date as "END_DATE",
COLUMN4::string as "NAME"
from (values
('2020-01-01','2020-01-01','2020-01-03','Name1'),
('2020-01-02',null,null,''),
('2020-01-03',null,null,''),
('2020-01-04',null,null,''),
('2020-01-05','2020-01-05','2020-01-05','Name2'),
('2020-01-06',null,null,'')
);

-- Create UDTF:
create or replace function 
    CONTINUE_UNTIL(CUR_DATE date, UNTIL date, VAL string, EMPTY_VAL string)
returns table (VAL string)
language javascript
strict immutable
as
$$
{
    initialize: function (argumentInfo, context) {
        this.val = null;
        this.until = null;
    },
    processRow: function (row, rowWriter, context) {
        if (row.UNTIL !== row.EMPTY_VAL && row.UNTIL != null) {
            this.until = row.UNTIL;
            this.val = row.VAL;
        }
        if (row.CUR_DATE <= this.until) {
            rowWriter.writeRow({VAL:this.val});
        } else {
            rowWriter.writeRow({VAL:row.EMPTY_VAL});
        }
    },
}
$$;

-- Call UDTF:
select DATES, VAL as NAME from T1
, table(CONTINUE_UNTIL(DATES, END_DATE, NAME, '') 
        over (partition by 1 order by DATES));

Output: Output:

DATES日期 NAME名称
2020-01-01 2020-01-01 Name1姓名1
2020-01-02 2020-01-02 Name1姓名1
2020-01-03 2020-01-03 Name1姓名1
2020-01-04 2020-01-04
2020-01-05 2020-01-05 Name2名字2
2020-01-06 2020-01-06

You could use a scalar subquery as the following:您可以使用标量子查询,如下所示:

SELECT DATES, 
  (SELECT Name FROM table_name D WHERE T.DATES BETWEEN D.START_DATE AND D.END_DATE) AS NAME
FROM table_name T

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM