我使用的是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,不是=)
答案 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;
根据您的样本数据,上述查询的结果是:
| 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;