SQL Logic根据给定方案合并两个表

时间:2016-05-20 20:50:52

标签: sql sql-server

  • 表1具有随机日期和相应值的Id。
  • 表2具有序列日期的id(它不一定是序列)。

将Table2.Id和Table2.SequenceDate与Table1.Id和Table.RandomDate匹配,然后需要应用theTable1。值到表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

4 个答案:

答案 0 :(得分:1)

我会使用子查询来获得预期值。

    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

答案 1 :(得分:1)

最后我得到了那个逻辑,感谢大家的所有投入。

       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

答案 2 :(得分:0)

这是一种方式

<强> SQL Fiddle DEMO

SELECT *
FROM Table2 t2
JOIN Table1 t1
  ON t2.[ID] = t1.[ID]
 AND t1.[RandomDate] = (SELECT MAX(t3.[RandomDate]) 
                        FROM Table1 t3 
                        WHERE t3.[RandomDate] <= t2.[SequenceDate])

<强>输出

| SequenceDate | ID |  RandomDate | value | ID |
|--------------|----|-------------|-------|----|
|  12 Feb 2016 |  1 | 12 Feb 2016 |     A |  1 |
|  13 Feb 2016 |  1 | 12 Feb 2016 |     A |  1 |
|  14 Feb 2016 |  1 | 12 Feb 2016 |     A |  1 |
|  15 Feb 2016 |  1 | 15 Feb 2016 |     B |  1 |
|  16 Feb 2016 |  1 | 15 Feb 2016 |     B |  1 |
|  17 Feb 2016 |  1 | 15 Feb 2016 |     B |  1 |
|  18 Feb 2016 |  1 | 18 Feb 2016 |     C |  1 |
|  19 Feb 2016 |  1 | 18 Feb 2016 |     C |  1 |
|  20 Feb 2016 |  1 | 18 Feb 2016 |     C |  1 |
|  12 Feb 2016 |  2 | 12 Feb 2016 |     A |  2 |

第二版:通过这种方式,您可以先创建范围,然后查看属于序列的范围。

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 |

答案 3 :(得分:0)

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
;

您肯定需要在Table2上使用适当的索引,例如(Id, RandomDate)

如果找不到匹配日期,则OUTER APPLY代替CROSS APPLY,以便NULL显示Value