【问题标题】:Selecting Active roles from denormalized table with duplicates从具有重复项的非规范化表中选择活动角色
【发布时间】:2015-03-12 05:59:42
【问题描述】:

我有一个垃圾表,需要从中提取数据。

 Name        | Person# | Assignment_Status | Group
 --------------------------------------------------
 Smith, John | 1234567 | NLE               | G1
 Smith, John | 1234567 | Active            | G2
 Jones, Jane | 7654321 | Active            | G1
 James, Jack | 9876541 | LOA               | G3
 Peep, Laura | 6549871 | ServiceLOA        | G1
 Some, One   | 3219875 | NLE               | G2

每次有人移动组时,他们当前的 assignment_status 都会设置为 NLE,并会创建一条新记录以将新组的 assignment_status 设置为 Active。当一个人离开公司时,他们还将 assignment_status 设置为 NLE。此表没有唯一的行 ID,也没有日期戳。

我需要一个查询,将表减少到每个员工 1 条记录,如果员工有多条记录,我需要非 NLE 的 Assignment_Status。例如,John Smith 应该显示为对 G2 有效。

我的第一次尝试是:

 SELECT *
 INTO #TempAssignments
 FROM
    (SELECT 
       ROW_NUMBER() OVER (ORDER BY aID) AS ID,
       Name,
       Person#,
       (CASE WHEN Assignment_Status='NLE' THEN 1 ELSE 0 END) AS aID,
       Group
     FROM
       tblAssignments)

使用临时表中的数据,然后我创建了第二个查询来选择 ID 的 MIN、aID 的 MIN 和 GROUP BY Name 和 Person#,然后将其连接回临时表以获取给定 ID 的组.

这似乎可行,但这是一个需要在多个报告中部署的解决方案,所以我想知道是否有更紧凑的方法来做到这一点。

【问题讨论】:

  • 如果你没有索引或者你的表很小,最好使用ROW_NUMBER()(当然不用GROUP BY)。如果您的表很大并且您可以在(Person#, Assignment_Status) 上创建一个索引,并且更好的是,如果您有一个单独的包含所有人列表的小表,那么使用CROSS APPLY 会更好。这里的“更好”是指更快。

标签: sql sql-server tsql


【解决方案1】:

以下查询:

SELECT Name, Person#, [Group]
FROM (
  SELECT Name, Person#, [Group],
         ROW_NUMBER() OVER (PARTITION BY Person#, Name 
                            ORDER BY CASE 
                                      WHEN Assignment_Status <> 'NLE' THEN 0 
                                      ELSE 1 
                                     END) AS rn
   FROM tblAssignments ) t
WHERE t.rn = 1

将为每位员工选择一条记录,由 Person#, Name 值对标识。如果员工有多个记录,则将选择不是NLEAssignment_Status 记录。

【讨论】:

    猜你喜欢
    • 2011-08-09
    • 2012-10-08
    • 1970-01-01
    • 2021-01-12
    • 2010-11-21
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多