使用另一个 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]
将您的 date
和 product
列反透视为一列。您可以使用 UNPIVOT
或 CROSS 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
这是数据:
[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]
将您的 date
和 product
列反透视为一列。您可以使用 UNPIVOT
或 CROSS 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