SQL:根据条件选择唯一值

时间:2013-07-31 11:31:43

标签: sql performance conditional

我有一个包含5列的表格。第一列包含ID,两列包含值为0或1的ID的参数,第三列包含我需要作为输出的参数,最后一列包含日期。相同的ID可以出现在具有不同参数的多行中:

ID        parameter1      parameter2        parameter3       date

001       0               1                 A                01.01.2010
001       0               1                 B                02.01.2010
001       1               0                 C                01.01.2010
001       1               1                 D                01.01.2010
002       0               1                 A                01.01.2010

对于我想在parameter3中返回值的每个唯一ID,返回此值的行的决定取决于parameter1parameter2中的值以及日期:

  • 如果有一行参数都是0,我想要这一行中的值。
  • 如果没有这样的行,我希望参数1为0且参数2为1的行中的值,
  • 如果没有这样的行,我想要参数1为1且参数2为0的行。
  • 最后,如果没有这样的行,我想要来自行的值,其中两个参数都是1

如果有多个行符合所需条件,我希望该行具有最新日期。

例如,对于上表,对于ID 001,我希望第二行在parameter3中具有值B

最有效/最快的方法是什么?到目前为止我尝试了两种方法:

第一个是选择所有不同的ID,然后使用select子句中带有ID的where语句循环遍历不同的ID,然后循环遍历与ID匹配的所有行将必要的值存储在变量中。:

foreach
    select distinct ID into i_ID from table1
        foreach
            let o_case = 5
            select case
                when parameter1 = 0 and parameter2 = 0 then 1
                when parameter1 = 0 and parameter2 = 1 then 2
                when parameter1 = 1 and parameter2 = 0 then 3
                when parameter1 = 1 and parameter2 = 1 then 4
                end, parameter3, date
                into i_case, i_p3, i_date
                from table3
                where table3.ID = i_ID

                if i_case < o_case 
                    then let o_p3, o_case, o_date = i_p3, i_case, i_date;
                    else ( if i_case = o_case and i_date > o_date
                        then let o_p3, o_date = i_p3, i_date;
                    end if;
                end if;
        end foreach;
        insert into table_output values(i_ID; o_p3);
end foreach;

第二种方法是将ID连接表四次,并应用参数1和amp;的不同组合。参数2如上左边连接中所述,然后通过嵌套的nvl子句选择输出:

select ID, 
    nvl(t1.parameter3, 
        nvl(t2.parameter3,
            nvl(t3.parameter3,
                nvl(t4.parameter3)))) parameter3
from table1 t0
    left join table1 t1
        on t0.ID = t1.ID and t1.parameter1 = 0 and t1.parameter2 = 0
        and t1.date = (select max(date) from table1 t1a where t1a.ID = t1.ID)        
    left join table1 t2
        on t0.ID = t2.ID and t2.parameter1 = 0 and t2.parameter2 = 1
        and t2.date = (select max(date) from table1 t2a where t2a.ID = t1.ID)
    left join table1 t3
        on t0.ID = t3.ID and t3.parameter1 = 1 and t3.parameter2 = 0
        and t3.date = (select max(date) from table1 t3a where t3a.ID = t3.ID)
    left join table1 t4
        on t0.ID = t4.ID and t4.parameter1 = 1 and t4.parameter2 = 1
        and t4.date = (select max(date) from table1 t4a where t4a.ID = t4.ID)

然而,这两种方法基本上都有效,因为表格很长,它们太慢了。你会推荐什么?

PS:DBMS是IBM Informix 10,遗憾的是这限制了可用功能的范围。

2 个答案:

答案 0 :(得分:1)

我不确定这是否是你想要的,但这可行:

SELECT id, parameter3
FROM (
    SELECT id, parameter3, RANK() OVER (
            PARTITION BY id, parameter3
            ORDER BY parameter1 ASC, parameter2 ASC, date DESC
        )
    FROM tab
) AS x
WHERE x.rank = 1;

答案 1 :(得分:0)

ID        parameter1      parameter2        parameter3       date

001       0               1                 A                01.01.2010
001       0               1                 B                02.01.2010

以上两行具有相同的ID,paramaeter1,parameter2但不同的paraameter3,可能会给你带来麻烦。