【问题标题】:join/merge 2 status tables (check statuses at any change)加入/合并 2 个状态表(随时检查状态)
【发布时间】:2013-10-16 07:07:59
【问题描述】:

我有 2 个表来指示对象的状态何时有效。我需要加入/合并/联合它们,这样我就可以在一张表中知道在任何给定更改时两个状态是什么。

表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))

有人有想法吗? 托梅克

【问题讨论】:

  • 为您的特定示例创建表格和数据的出色脚本。 +1

标签: sql sql-server tsql


【解决方案1】:

这是一个想法。首先,您将两个表合并,为其他表的状态留下空值,然后使用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

【讨论】:

    【解决方案2】:

    这对你有用吗?

    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
    

    【讨论】:

    • 如果不是这样,但很接近,请向我解释您如何确定在这些列中应该用什么代替 NULL。只是从以前的记录中删除它吗?如果是这样,您是否可以使用使用游标的存储过程?
    猜你喜欢
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多