TSQL从两行中选择优先级较高且不为空的行

时间:2012-03-29 13:51:10

标签: sql sql-server tsql

我尝试合并同一个表的两行,而每行都有一个优先级。 感兴趣的值是优先级为1的值,如果它不是NULL;否则优先级为0的值。

示例数据源可以是:

| Id | GroupId | Priority | Col1  | Col2  | Col3  | ... | Coln  |
-----------------------------------------------------------------
| 1  | 1       | 0        | NULL  | 4711  | 3.41  | ... | f00   |
| 2  | 1       | 1        | NULL  | NULL  | 2.83  | ... | bar   |    
| 3  | 2       | 0        | NULL  | 4711  | 3.41  | ... | f00   |
| 4  | 2       | 1        | 23    | NULL  | 2.83  | ... | NULL  |    

我希望:

| GroupId | Col1  | Col2  | Col3  | ... | Coln  |
-------------------------------------------------
| 1       | NULL  | 4711  | 2.83  | ... | bar   |    
| 2       | 23    | 4711  | 2.83  | ... | f00   |

TSQL中是否存在通用方法而无需明确检查每一列?

SELECT 
  t1.GroupId,
  ISNULL(t2.Col1, t1.Col1) as Col1,
  ISNULL(t2.Col2, t1.Col2) as Col2,
  ISNULL(t2.Col3, t1.Col3) as Col3,
  ...
  ISNULL(t2.Coln, t1.Coln) as Coln
FROM mytable t1
JOIN mytable t2 ON t1.GroupId = t2.GroupId
WHERE       
    t1.Priority = 0 AND
    t2.Priority = 1

此致

2 个答案:

答案 0 :(得分:0)

我认为如果不为每列使用isnull,这将会满足您的要求

select
   *
from
   mytable t1
where
   priority=(select max(priority) from mytable where groupid=t1.groupid group by groupid)

答案 1 :(得分:0)

我将详细阐述@KM建议的ROW_NUMBER()解决方案,因为IMO是最好的解决方案。 (以CTE形式,以便于阅读)

WITH cte AS (   
   SELECT
      t1.GroupId,
      t1.Col1,
      t1.Col2,
      ROW_NUMBER() OVER(PARTITION BY t1.GroupId ORDER BY ISNULL(GroupId ,-1) ) AS [row_id]
   FROM
      mytable t1
)
SELECT 
   *
FROM
   cte 
WHERE 
   row_id = 1

这将为mytable中的每个GroupId提供具有最高优先级的行(根据您的规则)。

ROW_NUMBER和RANK是我最喜欢的两个TSQL技巧。 http://msdn.microsoft.com/en-us/library/ms186734.aspx

编辑:我的另一个最喜欢的是PIVOT / UNPIVOT,您可以使用它来转置行/列,这是解决此类问题的另一种方式。 http://msdn.microsoft.com/en-us/library/ms177410.aspx