如果为true则返回一个值,如果不为真则返回另一个值

时间:2013-06-23 16:46:17

标签: sql sql-server select if-statement

我有以下示例表:

ID    Type    Price    Code    Date
 1      1       .99    Null    6/1
 2      2      1.99    Null    5/1
 3      1       .99    1234    4/1
 4      3      1.99    Null    5/1
 5      2      3.99    Null    6/1
 6      1      1.30    1234    5/1
 7      1      1.64    5673    6/10

我需要选择以下内容:Type,Price - 适用于所有类型,基于以下规则:

  1. 如果代码与请求匹配,请记录最新记录。
  2. 如果Type的所有代码都为Null,请记录最新记录。
  3. 因此,Code为'1234'的请求的结果集应为:

    ID:
    4 (This is the most recent record for type 3)
    5 (This is the most recent record for type 2)
    6 (This is the most recent record for type 1 having a code = '1234')
    

    我创建了以下查询:

    Select distinct 
        ID, Type, Price, Code, Date 
    from 
        tblPRODUCT 
    where 
        Code = '1234' OR Date IN (Select MAX(Date) from tblPRODUCT Group By Type)
    

    但这并没有给我正确的结果。想法?

3 个答案:

答案 0 :(得分:2)

Select 
    ID, Type, Price, Code, Date 
from 
    tblPRODUCT tbpr
where 
    (Code = '1234' AND Date IN (Select MAX(Date) from tblPRODUCT where type= tbpr.type   
and code = '1234'))
OR Date IN (Select MAX(Date) from tblPRODUCT where type= tbpr.type 
         and not exists(select code from tblPRODUCT where type= tbpr.type  and code is 
not null) ) 

这是如何运作的:

如果代码匹配,Ored条件的第一部分将选择该行。请注意,如果有多行与匹配相同ID的代码,则选择具有最大日期的行。

如果所有代码都为空,则第二个Ored条件将选择具有最大日期的行。

我对它进行了测试,它与您的采样数据完美配合,适用于您尝试的任何数据组合。

SQLFIDDLE:

http://www.sqlfiddle.com/#!3/19b03/18

答案 1 :(得分:1)

迟来的和类似于删除的答案,但只是为了显示比接受的答案稍微简单的方法;

WITH cte AS (
  SELECT *, 
  ROW_NUMBER() OVER(PARTITION BY Type ORDER BY Code DESC, Date DESC) rn
  FROM tblPRODUCT WHERE Code='1234' OR Code IS NULL
)
SELECT ID, Type, Price, Code, Date
FROM cte WHERE rn=1;

An SQLfiddle for testing

答案 2 :(得分:0)

经过一番思考后,这似乎相当复杂。您没有包含给定代码上所有类型的记录,因此您必须以某种方式生成它们。这表明使用了驱动程序表。

优先规则会使这有点复杂:

select coalesce(p.id, driver.id) as id,
       coalesce(p.[type], driver.[type]) as [type],
       coalesce(p.price, driver.price) as price,
       coalesce(p.code, driver.code) as code,
       coalesce(p.[date], driver.[date]) as [date]
from (select p.*
      from (select p.*, row_number() over (partition by [type]
                                           order by (case when [type] is NULL then 1 else 0 end) desc,
                                                    [date]
                                          ) as seqnum
            from tblProduct p
           ) p
       where seqnum = 1
     ) driver left outer join
     tblProduct p
     on p.code = XXX and
        p.type = driver.[type] and
        driver.type is NULL

类似的方法是使用union all来获取值:

select ID, Type, Price, Code, Date
from tblProduct p
where date = (select max(date) from tblProduct p2 where p2.code = p.code and p2.type = p.type) and
      code = XXX
union all
select id, type, price, code, Date
from tblProduct p
where code is null and
      date = (select max(date) from tblProduct p2 where p2.code = p.code and p2.type is null) and
      type not in (select type from tblProduct p2 where p2.code = p.code)

我意识到SQL代码看起来非常不同。但类似的想法是你必须从你正在寻找的代码中分别获取NULL代码的值。第一个使用驱动程序表,然后在select上执行逻辑。第二个做union all,将两个集合分成两个不同的集合。