2

我目前正在开发一个项目,该项目需要使用存储在 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

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

4

2 回答 2

1

虽然我同意 Bailey S. 的观点,即 Postgres 是“世界上最好的数据库引擎”,但我也看到您使用的是 SQL Server。

您需要的 MSSQL 函数称为“Pivot”函数,您可以在此处找到文档。

最初设置可能有点棘手,但它是完全可行的,并且会给你你正在寻找的结果。


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

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子句中列出时调用该表。如果您需要几列或者表有大量记录,则可能会降低性能。


另一种选择是一起使用 group & case 语句:

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 的事件开始时间可能出现两次,则不要使用它,因为其中一些记录将不会返回。

于 2012-10-31T20:52:25.733 回答
0

对于这样的场景,我喜欢使用一个技巧。这个想法是您希望将数据分组到一个 id。如果MAX()与 a 结合使用,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]

在这里,您可以看到它正在发挥作用。

请记住,这假设了某些约束。即,对于每个id, [Event Date]组合,只有:

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

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

于 2012-10-31T20:31:27.410 回答