基于给定场景合并两个表的SQL逻辑 表1的Id带有随机日期和相应的值。 表2的id带有序列日期,不一定是序列。
将Table2.Id和Table2.SequenceDate与Table1.Id和Table.RandomDate匹配,然后需要应用Table1。在下一个随机日期出现之前,将值添加到表2中 您可以在下面的预期结果中看到基于给定场景合并两个表的SQL逻辑 表1的Id带有随机日期和相应的值。 表2的id带有序列日期,不一定是序列。,sql,sql-server,Sql,Sql Server,将Table2.Id和Table2.SequenceDate与Table1.Id和Table.RandomDate匹配,然后需要应用Table1。在下一个随机日期出现之前,将值添加到表2中 您可以在下面的预期结果中看到 Table 1 RandomDate value ID 2/12/2016 A 1 2/15/2016 B 1 2/18/2016 C 1 2/12/2016 A 2 Table
Table 1
RandomDate value ID
2/12/2016 A 1
2/15/2016 B 1
2/18/2016 C 1
2/12/2016 A 2
Table 2
SequenceDate ID
2/12/2016 1
2/13/2016 1
2/14/2016 1
2/15/2016 1
2/16/2016 1
2/17/2016 1
2/18/2016 1
2/19/2016 1
2/20/2016 1
2/12/2016 2
Expected Result from table and table 2
SequenceDate ID value
2/12/2016 1 A
2/13/2016 1 A
2/14/2016 1 A
2/15/2016 1 B
2/16/2016 1 B
2/17/2016 1 B
2/18/2016 1 C
2/19/2016 1 C
2/20/2016 1 C
2/12/2016 2 A
我将使用子查询来获取期望值
select
Table2.SequenceDate,
Table2.ID,
( select top 1 Table1.Value
from Table1
where Table1.RandomDate <= Table2.SequenceDate
and Table1.ID = Table2.ID
order by Table1.RandomDate desc
) as Value
from Table2
这是一种方式
第二个版本:使用这种方法,首先创建范围,然后查看序列属于哪个范围
WITH Ranges as (
SELECT [ID],
[RandomDate] [start],
LEAD([RandomDate],1, NULL) OVER (PARTITION BY [ID]
ORDER BY [RandomDate]) [end],
[value]
FROM Table1
)
SELECT t2.[ID],
t2.[SequenceDate],
r.*
FROM Table2 t2
JOIN Ranges r
ON t2.[ID] = r.[ID]
AND t2.[SequenceDate] >= r.[start]
AND (t2.[SequenceDate] < r.[end] OR r.[end] IS NULL)
ORDER BY 1,2
在表2中,您肯定需要一个适当的索引,例如Id、RandomDate
外部应用而不是交叉应用是这样的,如果没有找到匹配的日期,值将显示空值。最后我得到了这个逻辑,谢谢大家的输入
SELECT
t2.Id,
t2.SequenceDate,
t1.RandomDate,
t1.Value,
ISNULL(LEAD(RandomDate,1,NULL) OVER (PARTITION BY Id ORDER BY Id,RandomDate),DATEADD(YEAR,99,RandomDate)) AS nextRandomDte,
ISNULL(LAG(RandomDate,1,NULL) OVER (PARTITION BY Id ORDER BY Id,RandomDate),RandomDate) AS prevRandomDte
FROM
dbo.table1 t1
RIGHT JOIN dbo.table2 t2
ON t1.Id = t2.Id
AND ( t2.SequenceDate >= t2.RandomDate OR
t2.RandomDate = prevRandomDte
)
AND t2.SequenceDate < nextRandomDte
什么数据库平台?您能发布您到目前为止尝试过的内容吗?这里的子查询作为独立集,id上没有连接谓词。因此它产生了错误的结果。@user3600663您是对的。我更正了查询,并将第三列命名为“Value”,正如您在问题说明中所做的那样。这需要2个连接而不是1个连接,有一种方法可以使用1来完成,它可能会执行得更好。@ErikE是的,我说。这是一种方式。我正试着和你一起做LEAD@ErikE但如果你有一个最快的方法,你应该张贴它。不确定LEAD是否会使用单个JOIN yetOkay,已发布。不确定它是否会更快。可能会。对于上面的示例表,它可能会工作,但如果在表1上添加了一些值,则会导致问题。如果您在表1上添加一些具有不同id和不同值(如x、y、z)的值,那么您将看到差异,因为在子查询中,我们只选择没有联接条件的max date
WITH Ranges as (
SELECT [ID],
[RandomDate] [start],
LEAD([RandomDate],1, NULL) OVER (PARTITION BY [ID]
ORDER BY [RandomDate]) [end],
[value]
FROM Table1
)
SELECT t2.[ID],
t2.[SequenceDate],
r.*
FROM Table2 t2
JOIN Ranges r
ON t2.[ID] = r.[ID]
AND t2.[SequenceDate] >= r.[start]
AND (t2.[SequenceDate] < r.[end] OR r.[end] IS NULL)
ORDER BY 1,2
| ID | | ID | start | end | value |
|----|-------------|----|-------------|-------------|-------|
| 1 | 12 Feb 2016 | 1 | 12 Feb 2016 | 15 Feb 2016 | A |
| 1 | 13 Feb 2016 | 1 | 12 Feb 2016 | 15 Feb 2016 | A |
| 1 | 14 Feb 2016 | 1 | 12 Feb 2016 | 15 Feb 2016 | A |
| 1 | 15 Feb 2016 | 1 | 15 Feb 2016 | 18 Feb 2016 | B |
| 1 | 16 Feb 2016 | 1 | 15 Feb 2016 | 18 Feb 2016 | B |
| 1 | 17 Feb 2016 | 1 | 15 Feb 2016 | 18 Feb 2016 | B |
| 1 | 18 Feb 2016 | 1 | 18 Feb 2016 | (null) | C |
| 1 | 19 Feb 2016 | 1 | 18 Feb 2016 | (null) | C |
| 1 | 20 Feb 2016 | 1 | 18 Feb 2016 | (null) | C |
| 2 | 12 Feb 2016 | 2 | 12 Feb 2016 | (null) | A |
SELECT
t2.SequenceDate,
t2.Id,
t1.Value
FROM
dbo.Table2 t2
OUTER APPLY (
SELECT TOP 1 t1.*
FROM dbo.Table1 t1
WHERE
t1.Id = t2.Id
AND t1.RandomDate <= t2.SequenceDate
ORDER BY
t1.RandomDate DESC
) t1
;
SELECT
t2.Id,
t2.SequenceDate,
t1.RandomDate,
t1.Value,
ISNULL(LEAD(RandomDate,1,NULL) OVER (PARTITION BY Id ORDER BY Id,RandomDate),DATEADD(YEAR,99,RandomDate)) AS nextRandomDte,
ISNULL(LAG(RandomDate,1,NULL) OVER (PARTITION BY Id ORDER BY Id,RandomDate),RandomDate) AS prevRandomDte
FROM
dbo.table1 t1
RIGHT JOIN dbo.table2 t2
ON t1.Id = t2.Id
AND ( t2.SequenceDate >= t2.RandomDate OR
t2.RandomDate = prevRandomDte
)
AND t2.SequenceDate < nextRandomDte