将存储的事件转换为单个记录

时间:2012-10-31 20:01:19

标签: sql algorithm parsing

我目前正在开发一个项目,需要以下面显示的格式利用存储在SQL数据库中的数据。

我需要做的是,并且很难找到一个可以帮助的工具,就是获取这些数据并创建一个键入ID和事件日期的多列单个记录。虽然我在网上发现了一些关于事件驱动处理程序的信息,但问题在于,尽管我的标签上写着“事件”,但实际存储的是称为“事件”的单个数据片段,这些数据实际上是单独的条目,但通常(但并非总是如此)同时输入并为整个事件输入做出贡献。我很抱歉,如果这看起来有点令人困惑,但我正在使用一个我无法控制的系统来改变我只需要对数据有用。

以下是我需要转换为单个记录的数据库中存储内容的运行示例;

ID      Event           Event Result  Event Result Value            Event Date      Entered By
909909  Status Change       No          no                          10/25/12 23:10  Doe, John
909909  Disposition         Remuni      Remains in place            10/25/12 23:10  Doe, John
909909  Event duration      15mins      15mins                      10/25/12 23:10  Doe, John
909909  Event end time      23:25       23:25                       10/25/12 23:10  Doe, John
909909  Event start time    23:10       23:10                       10/25/12 23:10  Doe, John
909909  Event type          Iniqrs      Initial System activation   10/25/12 23:10  Doe, John

进入以下单个记录;

ID      Event Start Event End   Moved               Action Taken                Entered By
909909  23:10       23:25       Remains in place    Initial System activation   Doe, John

提前感谢您提供任何帮助。

2 个答案:

答案 0 :(得分:1)

虽然我同意Bailey S.,Postgres是“地球上最好的数据库引擎”,但我也看到你使用的是SQL Server。

您需要的MSSQL功能称为“Pivot”功能,您可以找到文档here

最初设置可能有点棘手,但它完全可行,并且会为您提供所需的结果。


或者,有一种称为“自联接”的技术,它看起来像这样:

SELECT
    [T1].[ID],
    [StatusChange].[EventResultValue] AS 'StatusChange',
    [Disposition].[EventResultValue] AS 'Disposition',
    ...
FROM
    (
        SELECT DISTINCT
            [EventsTable].[ID]
        FROM
            [EventsTable]
    ) AS [T1] LEFT OUTER JOIN
    [EventsTable] AS [StatusChange] ON [T1].[ID] = [StatusChange].[ID] AND [StatusChange].[Event] = 'Status Change' LEFT OUTER JOIN
    [EventsTable] AS [Disposition] ON [T1].[ID] = [Disposition].[ID] AND [Disposition].[Event] = 'Disposition' LEFT OUTER JOIN
    ...

有点警告:
如果您使用此技术,它将在每次FROM子句中列出时调用该表。可能存在性能损失,您需要多列或者表中有大量记录。


另一种选择是使用一组&案例陈述:

SELECT
    [ID],
    MAX(CASE WHEN [Event] = 'Status Change' THEN [EventResult] ELSE NULL END) AS [Event Start],
    MAX(CASE WHEN [Event] = 'Disposition' THEN [EventResult] ELSE NULL END) AS [Event End]
    ...
FROM
    [EventsTable]
GROUP BY
    [ID]

更多警告:
如果您使用此技术,则保证每[ID]只返回一条记录。如果您有多个相同类型的事件(即,任何给定ID的事件开始时间可能会出现两次,那么不要使用此,因为其中一些记录将不会被返回。

答案 1 :(得分:0)

有一个技巧我喜欢突破这样的场景。我们的想法是,您希望将数据分组为一个ID。如果您将MAX()CASE结合使用,则基本上可以从该组中的所需行中选择一个值,并将其转换为结果集中的列。
这是查询:

select
  id,
  max(case when Event = 'Event start time' then [Event Result Value]
    else null end) as [Event Start],
  max(case when Event = 'Event end time' then [Event Result Value]
    else null end) as [Event End],
  max(case when Event = 'Disposition' then [Event Result Value]
    else null end) as [Moved],
  max(case when Event = 'Event type' then [Event Result Value]
    else null end) as [Action Taken],
  max([Entered By]) as [Entered By]
from Table1
group by id, [Event Date]

here你可以看到它正在发挥作用。

请记住,这假定了某些限制。也就是说,对于每个id, [Event Date]组合,只有:

  • 一个唯一的[输入者]值
  • 一行,事件='事件开始时间'
  • 一行,事件='事件结束时间'
  • 使用Event ='Disposition'
  • 的一行
  • 一行,事件='事件类型'

注意: 此查询按Event Date分组。这意味着具有相同日期但不同时间的记录将被视为单独组的一部分。如果您有两组记录,其中时间戳记在同一天但两个时间不同,那么这将按预期工作。另一方面,如果记录的时间戳稍微偏离,则可能会将记录从其预期组中排除。您只需要确保您的组具有一致的时间戳。