使用另一个 table 的最新值更新多个列

Update several columns with latest values from another table

这是数据:

[TABLE_1]

id | prod1  | date1  | prod2  | date2  | prod3  | date3 |
---|--------|--------|--------|--------|--------|-------|
1  | null   | null   | null   | null   | null   | null  |
2  | null   | null   | null   | null   | null   | null  |
3  | null   | null   | null   | null   | null   | null  |

[TABLE_2]

id   |  date       |   product |  
-----|-------------|-----------|
1    |  20140101   |   X       | 
1    |  20140102   |   Y       | 
1    |  20140103   |   Z       | 

2    |  20141201   |   data    | 
2    |  20141201   |   Y       | 
2    |  20141201   |   Z       | 

3    |  20150101   |   data2   | 
3    |  20150101   |   data3   | 
3    |  20160101   |   X       | 

两个表都有此处未列出的其他列。 date 的格式为:yyyymmdd,数据类型为 int[ TABLE_2 ] 没有空行,只是试图使上面的示例更具可读性。

这是目标:

我需要更新 [ TABLE_1 ] prod1,date1,prod2,date2,prod3,date3 product[ TABLE_2 ] 中收集并具有相应的 date 值。

必须对数据进行排序,使 "latest" product 变为 prod1, 最新的第二个 product 将是 prod2,第三个是 prod3.

最新 product = 最大 date (int)。 如果日期相等,则顺序无关紧要。 (参见 id=2 和 id=3)。

更新后的 [ TABLE_1 ] 应该是:

id | prod1  | date1    | prod2  | date2    | prod3  | date3    |
---|--------|----------|--------|----------|--------|----------|
1  | Z      | 20140103 | Y      | 20140102 | X      | 20140101 |  
2  | data   | 20141201 | Y      | 20141201 | Z      | 20141201 |  
3  | X      | 20160101 | data2  | 20150101 | data3  | 20150101 |

最终目标是获得以下内容:

[TABLE_3]

id | order1             | order2               | order3     |  + Columns from [ TABLE_1 ]
---|--------------------|----------------------|------------|--------------------------
1  | 20140103:Z         | 20140102:Y           | 20140103:Z |
2  | 20141201:data:Y:Z  | NULL                 | NULL       |
3  | 20160101:X         | 20150101:data2:data3 | NULL       |

我不得不承认这超出了我的知识范围,我还没有尝试过任何东西。

我应该使用 JOIN 还是 SELECT 子查询?

我应该尝试在一个 SQL 子句中完成还是分 3 个步骤完成, 每个 prod&date - 对当时?

创建 [ TABLE_3 ] 怎么样? 它必须包含来自 [ TABLE_1 ] 的列。 从 [ TABLE_2 ] -data 或更新的 [ TABLE_1 ] 创建它最容易吗?

如有任何帮助,我们将不胜感激。 提前致谢。

我会 post 一些我自己的镜头在评论中。

施工:

WITH ranked AS (
    SELECT [id]
          ,[date]
          ,[product]
          ,row_number() over (partition by id order by date desc) rn
      FROM [sistemy].[dbo].[TABLE_2]
)
SELECT id, [prod1],[date1],[prod2],[date2],[prod3],[date3]  
FROM 
(
    SELECT id, type+cast(rn as varchar(1)) col, value
    FROM ranked
    CROSS APPLY 
    (
        SELECT 'date', CAST([date] AS varchar(8))
        UNION ALL
        SELECT 'prod', product
    ) ca(type, value)
) unpivoted 
PIVOT
(
    max(value)
    for col IN ([prod1],[date1],[prod2],[date2],[prod3],[date3])
) pivoted

您需要采取一些步骤才能实现目标。

按日期对您的产品进行排名:

SELECT [id]
  ,[date]
  ,[product]
  ,row_number() over (partition by id order by date desc) rn
FROM [sistemy].[dbo].[TABLE_2]

将您的 dateproduct 列反透视为一列。您可以使用 UNPIVOTCROSS APPLY 语句。我更喜欢CROSS APPLY

SELECT id, type+cast(rn as varchar(1)) col, value
FROM ranked
CROSS APPLY 
(
    SELECT 'date', CAST([date] AS varchar(8))
    UNION ALL
    SELECT 'prod', product
) ca(type, value)

或使用 UNPIVOT

相同的结果
SELECT id, type+cast(rn as varchar(1)) col, value
FROM (
    SELECT [id], 
        rn, 
        CAST([date] AS varchar(500)) date, 
        CAST([product] AS varchar(500)) prod 
    FROM ranked) t
UNPIVOT 
(
    value FOR type IN (date, product)
) unpvt

最后你使用 PIVOTE 并得到一个结果。

在调查之后(在我的评论之后),一个存储过程将是最好的,你可以调用它来查看数据作为一个数据透视表,并取消 TABLE_1。显然,如果您需要使其动态化,则需要研究动态枢轴,这对 CTE 来说有点麻烦:

CREATE PROCEDURE DBO.VIEW_AS_PIVOTED_DATA

AS

;WITH CTE AS (
SELECT ID, [DATE], 'DATE' + CAST(ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [DATE] DESC) AS VARCHAR) AS [RN]
FROM TABLE_2)
, CTE2 AS (
SELECT ID, PRODUCT, 'PROD' + CAST(ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [DATE] DESC) AS VARCHAR) AS [RN]
FROM TABLE_2)
, CTE3 AS (
SELECT ID, [DATE1], [DATE2], [DATE3]
FROM CTE
PIVOT(MAX([DATE]) FOR RN IN ([DATE1],[DATE2],[DATE3])) PIV)
, CTE4 AS (
SELECT ID, [PROD1], [PROD2], [PROD3]
FROM CTE2
PIVOT(MAX(PRODUCT) FOR RN IN ([PROD1],[PROD2],[PROD3])) PIV)
SELECT A.ID, [PROD1], [DATE1], [PROD2], [DATE2], [PROD3], [DATE3]
FROM CTE3 AS A
JOIN CTE4 AS B
ON A.ID=B.ID