我有2个表,表明对象的状态何时有效。我需要加入/合并/联合它们,所以我在一个表中知道在任何给定的更改中两个stuses是什么。
表1:
Object status1 date
Obj1 Open 1998-01-01 00:00:00.000
Obj1 Closed 2000-06-01 00:00:00.000
Obj1 Open 2008-03-06 00:00:00.000
Obj1 Closed 2013-01-01 00:00:00.000
表2:
Object status2 date
Obj1 ACTIVE 1999-01-01 00:00:00.000
Obj1 INACTIV 2000-08-29 00:00:00.000
Obj1 UNKNOWN 2004-05-06 00:00:00.000
Obj1 check 2014-05-01 00:00:00.000
结果我需要这样的东西:
Object status1 status2 date
Obj1 Open NULL 1998-01-01 00:00:00.000
Obj1 Open ACTIVE 1999-01-01 00:00:00.000
Obj1 Closed ACTIVE 2000-06-01 00:00:00.000
Obj1 Closed INACTIV 2000-08-29 00:00:00.000
Obj1 Closed UNKNOWN 2004-05-06 00:00:00.000
Obj1 Open UNKNOWN 2008-03-06 00:00:00.000
Obj1 Closed UNKNOWN 2013-01-01 00:00:00.000
Obj1 Closed check 2014-05-01 00:00:00.000
这里是创建源表的脚本:
CREATE TABLE [dbo].[table2](
[Object] [nvarchar](1000) NULL,
[status2] [nvarchar](1000) NULL,
[date] [datetime] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[table2] ([Object], [status2], [date]) VALUES (N'Obj1', N'ACTIVE', CAST(0x00008D3F00000000 AS DateTime))
INSERT [dbo].[table2] ([Object], [status2], [date]) VALUES (N'Obj1', N'INACTIV', CAST(0x00008F9D00000000 AS DateTime))
INSERT [dbo].[table2] ([Object], [status2], [date]) VALUES (N'Obj1', N'UNKNOWN', CAST(0x000094DF00000000 AS DateTime))
INSERT [dbo].[table2] ([Object], [status2], [date]) VALUES (N'Obj1', N'check', CAST(0x0000A31E00000000 AS DateTime))
go
CREATE TABLE [dbo].[table1](
[Object] [nvarchar](1000) NULL,
[status1] [nvarchar](1000) NULL,
[date] [datetime] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[table1] ([Object], [status1], [date]) VALUES (N'Obj1', N'Open', CAST(0x00008BD200000000 AS DateTime))
INSERT [dbo].[table1] ([Object], [status1], [date]) VALUES (N'Obj1', N'Closed', CAST(0x00008F4400000000 AS DateTime))
INSERT [dbo].[table1] ([Object], [status1], [date]) VALUES (N'Obj1', N'Open', CAST(0x00009A5700000000 AS DateTime))
INSERT [dbo].[table1] ([Object], [status1], [date]) VALUES (N'Obj1', N'Closed', CAST(0x0000A13900000000 AS DateTime))
谁有个主意呢?
托梅克
答案 0 :(得分:0)
这是一个想法。首先,将两个表联合起来,为其他表的状态保留空值,然后使用case
和相关的子查询将空值填入上一个先前存在的值。
WITH CTE_Union AS
(
SELECT [Object], status1, NULL AS status2, [date] FROM dbo.Table1
UNION
SELECT [Object], NULL AS Status1, status2, [date] FROM dbo.Table2
)
, CTE_RN AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY [Object] ORDER BY [date]) RN
FROM CTE_Union
)
SELECT
r1.[Object]
,CASE WHEN r1.status1 IS NULL THEN (SELECT status1
FROM CTE_RN r2
WHERE r2.RN = (SELECT MAX(RN)
FROM CTE_RN r3
WHERE r3.status1 IS NOT NULL AND r3.RN < r1.RN))
ELSE r1.status1
END AS status1
,CASE WHEN r1.status2 IS NULL THEN (SELECT status2
FROM CTE_RN r2
WHERE r2.RN = (SELECT MAX(RN)
FROM CTE_RN r3
WHERE r3.status2 IS NOT NULL AND r3.RN < r1.RN))
ELSE r1.status2
END AS status2
,[date]
FROM CTE_RN r1
ORDER BY RN
<强> SQLFiddle DEMO 强>
答案 1 :(得分:0)
这对你有用吗?
select
isnull(t1.object,t2.object) Object
,status1
,status2
,isnull(t1.date,t2.date) date
from table1 t1
full join table2 t2
on t1.Object = t2.Object
and t1.date = t2.date
order by 4