SQL大于IN

时间:2015-08-03 12:24:29

标签: sql postgresql

我使用的是Postgres 9.4并想做类似的事情:

movement_id|counter|standardized_output
---------------------------------------
1          |      3|                 10
1          |      3|                 12
1          |      5|                 10
2          |      4|                  5

我有以下查询:

SELECT movement_id, counter, MAX(standardized_output) AS standardized_output 
FROM "outputs" 
WHERE "outputs"."user_id" = 1 AND "outputs"."movement_id" IN (1,2) AND (counter in (1,3,5)) 
GROUP BY movement_id, counter

这给了我:

movement_id|counter|standardized_output
---------------------------------------
1          |      3|                 12
1          |      5|                 10

但我想要找到的是counter >= (1,3,5)的MAX(standards_output)。所以结果如下:

movement_id|counter|standardized_output
---------------------------------------
1          |      1|                 12 (MAX value where movement_id is 1 and counter is >=1)
1          |      3|                 12 (MAX value where movement_id is 1 and counter is >=3)
1          |      5|                 10 (MAX value where movement_id is 1 and counter is >=5)
2          |      1|                  5 (MAX value where movement_id is 2 and counter is >=1)
2          |      3|                  5 (MAX value where movement_id is 2 and counter is >=3)
2          |      5|               null (MAX value where movement_id is 2 and counter is >=5)

(小编辑:movement_id是IN,不是=)

5 个答案:

答案 0 :(得分:0)

您可以在计数器字段上添加CASE语句吗?

CASE WHEN counter >= 5 THEN 5
WHEN counter >=3 THEN 3
WHEN counter >=1 THEN 1
ELSE 0 END

然后将其添加到select和group by子句中。

SELECT movement_id,
    (CASE WHEN counter >= 5 THEN 5
      WHEN counter >=3 THEN 3
      WHEN counter >=1 THEN 1
      ELSE 0 END) as new_counter,
    MAX(standardized_output) AS standardized_output 
FROM "outputs" 
WHERE "outputs"."user_id" = 1 AND "outputs"."movement_id" = 1
GROUP BY movement_id,
    (CASE WHEN counter >= 5 THEN 5
      WHEN counter >=3 THEN 3
      WHEN counter >=1 THEN 1
      ELSE 0 END)

答案 1 :(得分:0)

我准备在Kez所做的内容中发布一些内容(使用case语句),但有点不同。

我不确定在这种情况下您需要哪些条件,我不知道计数器> =(1,3,5)是否可以转换为计数器> = 5?在下面的示例中,我正在考虑计数器> =(1,3,5)意味着计数器> = 5(问题是如何理解这里的分号 - 如果要将它们翻译成AND或OR-我去了AND,所以计数器> =(1,3,5)与计数器> = 5相同,但如果要将分号理解为OR,则表示计数器值为2或4是您感兴趣的)

在任何情况下,无论你不想在max函数中考虑标准输出的任何条件,都要将它们包含在case条件中并让它们的计数器返回零,这样它不会影响你的最大值(或者是负值)号码,如果需要的话)

SELECT 
       movement_id,
       counter,
       MAX(CASE WHEN COUNTER < 1 THEN 0 ELSE COUNTER END ) AS standardized_output
  FROM outputs
 WHERE
   outputs.user_id = 1
   AND outputs.movement_id = 1
   AND counter in (1, 3, 5)
 GROUP BY movement_id, counter

答案 2 :(得分:0)

您可以使用CASE语句与MAX()函数一样使用

SELECT movement_id, 
counter, 
MAX(CASE WHEN movement_id = 1 and counter >= 1 THEN standardized_output
WHEN movement_id = 1 and counter >= 3 THEN standardized_output
WHEN movement_id = 1 and counter >= 5 THEN standardized_output
WHEN movement_id = 2 and counter >= 1 THEN standardized_output
WHEN movement_id = 2 and counter >= 3 THEN standardized_output
WHEN movement_id = 2 and counter >= 5 THEN standardized_output
ELSE NULL END) AS standardized_output 
FROM "outputs" 
WHERE "outputs"."user_id" = 1 
AND "outputs"."movement_id" = 1 
AND (counter in (1,3,5)) 
GROUP BY movement_id, counter;

答案 3 :(得分:0)

除非我完全误解了你想要做的事情,否则你应该能够通过加入处理这个问题:

SELECT o.movement_id,
    o.counter_id,
    MAX(oagg.standardized_output) AS standardized_output
FROM outputs o
LEFT JOIN outputs oagg
    ON  o.user_id       =  oagg.user_id
    AND o.other_primary =  oagg.other_primary
    AND o.movement_id   =  oagg.movement_id
    AND o.counter_id    <= oagg.counter_id
WHERE o.user_id = 1;

如果你明确地想要不存在的counter_id,你需要以某种方式创建它们。我可能会加入一个计数表,但我不确定我是否完全明白你在寻找什么。

答案 4 :(得分:0)

如果您想要没有任何值的行的结果,首先需要创建一个由应该存在的行组成的集合,在这种情况下是{movement_id} X {1,3,5}的笛卡尔积。为此,我们可以使用交叉连接和表值构造函数,然后它只是使用左连接和子查询来获取最大值。

我确定此查询可以改进,但它应该有效。

select 
    all_values.movement_id, 
    all_values.num, 
    (   
       select max(standardized_output) 
       from outputs 
       where counter >= all_values.num 
         and movement_id = all_values.movement_id
    ) as standardized_output 
from (
  select movement_id, t.num
  from outputs
  cross join (values (1), (3), (5)) as t(num) 
  where "movement_id" in (1 ,2)
-- and "outputs"."user_id" = 1 --this was missing in your sample so I left it commented out.
) all_values
left join outputs o on all_values.movement_id = o.movement_id
                   and (counter in (all_values.num)) 
group by all_values.movement_id, all_values.num
order by all_values.movement_id, all_values.num;

Sample SQL Fiddle

根据您的样本数据,上述查询的结果是:

| movement_id | num | standardized_output |
|-------------|-----|---------------------|
|           1 |   1 |                  12 |
|           1 |   3 |                  12 |
|           1 |   5 |                  10 |
|           2 |   1 |                   5 |
|           2 |   3 |                   5 |
|           2 |   5 |              (null) |

编辑:使用此查询可以获得相同的结果:

select  
  o1.movement_id, 
  t.num as counter, 
  max(o2.standardized_output) as standardized_output
from outputs o1 cross join (values (1), (3), (5)) as t(num) 
left join outputs o2 on o1.movement_id = o2.movement_id and t.num <= o2.counter
where o1.movement_id in (1,2) 
group by o1.movement_id, t.num
order by o1.movement_id, t.num;

Sample fiddle