在select语句中使用Case

时间:2015-05-06 16:45:29

标签: sql sql-server

考虑下表

create table temp (id int, attribute varchar(25), value varchar(25))

并将值放入表中

insert into temp select 100, 'First', 234
insert into temp select 100, 'Second', 512
insert into temp select 100, 'Third', 320
insert into temp select 101, 'Second', 512
insert into temp select 101, 'Third', 320

我必须推断一个依赖于'属性'的EndResult列。柱。对于每个id,我必须按顺序解析属性值 First,Second,Third选择第一个可用的值,即对于id = 100,EndResult应为234,用于前三个记录。

预期结果:

|  id | EndResult |
|-----|-----------|
| 100 |       234 |
| 100 |       234 |
| 100 |       234 |
| 101 |       512 |
| 101 |       512 | 

我徒劳地尝试了以下查询:

select id, case when isnull(attribute,'') = 'First'
                then value
            when isnull(attribute,'') = 'Second'
                then value         
            when isnull(attribute,'') = 'Third'
                then value    
            else '' end as EndResult
from
temp

结果

|  id | EndResult |
|-----|-----------|
| 100 |       234 |
| 100 |       512 |
| 100 |       320 |
| 101 |       512 |
| 101 |       320 |

请建议是否有办法获得预期的结果。

4 个答案:

答案 0 :(得分:3)

您可以使用dense_rank之类的分析功能生成编号,然后选择编号为' 1'

的行
select
  x.id,
  x.attribute,
  x.value
from
  (select
    t.id,
    t.attribute,
    t.value,
    dense_rank() over (partition by t.id order by t.attribute) as priority
  from
    Temp t) x
where
  x.priority = 1

在您的情况下,您可以方便地按t.attribute订购,因为他们的字母顺序恰好是正确的顺序。在其他情况下,您可以使用案例将属性转换为数字,例如:

order by 
  case t.attribute 
    when 'One' then 1 
    when 'Two' then 2 
    when 'Three' then 3 
  end

答案 1 :(得分:2)

如果属性列具有不同于上面字母顺序的值,则可以写为:

with cte as
(
  select id,
         attribute,
         value,
         case attribute when 'First' then 1
                        when 'Second' then 2 
                        when 'Third' then 3 end as seq_no 
         from temp
  )
  , cte2 as 
  ( 
    select id,
           attribute,
           value,
           row_number() over ( partition by id order by seq_no asc) as rownum
     from cte
    ) 
    select T.id,C.value as EndResult
    from temp T
    join cte2 C on T.id = C.id and C.rownum = 1

DEMO

答案 2 :(得分:1)

以下是使用ROW_NUMBER()

实现此目的的方法
WITH t
AS (
    SELECT *
        ,ROW_NUMBER() OVER (
            PARTITION BY id ORDER BY (CASE attribute WHEN 'First' THEN 1 
                                                     WHEN 'Second' THEN 2 
                                                     WHEN 'Third' THEN 3 
                                      ELSE 0 END)
            ) rownum
    FROM TEMP
    )
SELECT id
    ,(
        SELECT value
        FROM t t1
        WHERE t1.id = t.id
            AND rownum = 1
        ) end_result
FROM t;

出于测试目的,请参见SQL Fiddle演示:

SQL Fiddle Example

答案 3 :(得分:0)

保持简单

;with cte as
(
    select  row_number() over (partition by id order by (select 1)) row_num, id, value
    from    temp
)
select  t1.id, t2.value
from    temp t1
            left join cte t2
            on t1.Id = t2.id
where   t2.row_num = 1

结果

id   value
100  234
100  234
100  234
101  512
101  512