Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基于给定场景合并两个表的SQL逻辑 表1的Id带有随机日期和相应的值。 表2的id带有序列日期,不一定是序列。_Sql_Sql Server - Fatal编程技术网

基于给定场景合并两个表的SQL逻辑 表1的Id带有随机日期和相应的值。 表2的id带有序列日期,不一定是序列。

基于给定场景合并两个表的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

将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 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