case对应的对象给出不正确的值

时间:2016-05-05 15:57:07

标签: sql postgresql postgresql-9.1

查询结果如下:

 b_id| l_id | result    | Count | avg
-----+------+--------- -+-------+-----
   1 |   10 | Limited   |   2   | 66.66
   1 |   10 |Significant|   1   | 33.33
   2 |   09 | Critical  |   1   |100.00  

我正在努力使用case语句进行查询,如下所示:

SELECT DISTINCT ON (b_id, l_id) b_id, l_id, 
            (CASE
                WHEN result = 'Critical' THEN 'Critical'
                WHEN result = 'Significant' AND avg >= 50 THEN 'Critical'
                WHEN result = 'Significant' AND result <> 'Critical' THEN 'Significant'
                WHEN result = 'Medium' AND avg >= 50 THEN 'Medium'
                ELSE 'Limited' END) as cr                   
From (sub query)

我得到的结果如下:

 b_id| l_id | result    
-----+------+----------
   1 |   10 | Limited   
   2 |   09 | Critical

但我期待的是如下:

 b_id| l_id | result    
-----+------+----------
   1 |   10 | significant   
   2 |   09 | Critical

1)。如果至少有一个关键,那么至关重要。 2)当有显着=> 50%并且没有关键然后是关键的(这意味着如果只有1行而且很重要,那么它是100%那么关键&#39;) 3)如果至少有1个重要的,没有关键的和(中等的,有限的)&gt;显着然后显着  4)如果培养基> = 50%且没有(关键或显着)则培养基  5)休息将是有限的。

我需要显着而不是有限,因为在大多数情况下最高值胜过较低的值所以Sig trumps Ltd.总的来说我希望case语句来评估对的组(b_id,l_id)所以在1对的组中| 10我需要案例陈述来评估并返回结果。

4 个答案:

答案 0 :(得分:1)

除了WHEN result = 'Significant' AND result <> 'Critical' THEN 'Significant'问题*之外,所有三行都符合条件,然后由于DISTINCT ON (b_id, l_id)而选择前两行中的一行。您无法控制将选择哪两行,这基本上是您的数据在磁盘上的组织方式以及可能随时间变化的函数。

您永远不会获得1 | 10 | Critical行,因为表格中的相应行包含result = 'Significant',但avg = 33.33因此不能成为'Critical'。如果您希望使用“严重”而不是“中”而非“限制”的行,则应为此添加特定子句,例如为每个result级别分配数值的表这样你就可以对它进行排序。

* CASE语句仅在获得最终结果时进行评估,因此当第一个子句匹配时,不评估剩余子句。

答案 1 :(得分:1)

使用bool_or聚合(至少条件对于一行为真):

SELECT b_id, l_id,CASE WHEN bool_or(result='Critical' or (result = 'Significant' AND avg >= 50) ) Then 'Critical' 
           WHEN bool_or(result='Significant') THEN 'Significant'
           WHEN bool_or(result = 'Medium' AND avg >= 50) THEN 'Medium'
           ELSE 'Limited' END as cr 
 From (sub query) group by 1,2

答案 2 :(得分:0)

Patrick's answer是正确的,但我会对其进行扩展,以使查询中的矛盾/问题更加明确。

您开始使用的表格或子查询包含这些 3 行,如果您考虑其列的全部,则每个行都是不同的:

 b_id| l_id | result    | Count | avg
-----+------+--------- -+-------+-----
   1 |   10 | Limited   |   2   | 66.66
   1 |   10 |Significant|   1   | 33.33
   2 |   09 | Critical  |   1   |100.00  

但是,您运行的查询使用的DISTINCT ON仅包含 2 列:

SELECT DISTINCT ON (b_id, l_id) b_id, l_id, …

你在这里明确告诉PostgreSQL的是,“我只想看到不同的输出行,但是我想让你考虑两个输出行在{{仅> 上对{ {1}}和b_id列。“

存在矛盾:

  • 如果您考虑所有
  • ,则所有3行都是不同的
  • ... l_id只有两个不同的元组:(b_id, l_id)(1,10)

因为你特意告诉PostgreSQL将前两行视为不是,所以它只选择一行来输出这些行,然后选择这一行任意帕特里克解释说。

我不确定您为什么首先使用(2,09)。如果您只是将其替换为DISTINCT ON (x, y, z)(在所有列上),则查询将返回您期望的结果:

DISTINCT

(我还删除了其他人注意到的冗余SELECT DISTINCT b_id, l_id, (CASE WHEN result = 'Critical' THEN 'Critical' WHEN result = 'Significant' AND avg >= 50 THEN 'Critical' WHEN result = 'Significant' THEN 'Significant' WHEN result = 'Medium' AND avg >= 50 THEN 'Medium' ELSE 'Limited' END) as cr From (sub query) 。)

答案 3 :(得分:0)

select b_id, l_id, (CASE WHEN result = 'Critical' THEN 'Critical'
            WHEN (result = 'Significant' AND avg >= 50) THEN 'Critical'
            WHEN result = 'Significant' THEN 'Significant'
            WHEN result = 'Medium' AND avg >= 50 THEN 'Medium'
            WHEN result = 'Limited' THEN 'Limited' END) as result
from (
    select business_unit_id, law_id, result, avg
from (
    SELECT b_id, l_id, avg, result, ROW_NUMBER() over(PARTITION BY b_id, l_id order by CASE
            WHEN result = 'Critical' THEN 1
            WHEN result = 'Significant' AND avg >= 50 THEN 1
            WHEN result = 'Significant' THEN 2
            WHEN result = 'Medium' AND avg >= 50 THEN 3
            WHEN result = 'Limited' THEN 4 END) as rownum

from (
    sub_query     ) b            ) x where rownum = 1              ) y