我使用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但是,我想要找到的是最大的(Standardized_output)是什么counter >= (1,3,5)。结果如下:
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,not =)
发布于 2015-08-03 13:07:10
由于您希望对没有任何值的行产生结果,所以首先需要创建一个由应该存在的行组成的集合,在本例中是{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;示例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;样品小提琴
发布于 2015-08-03 12:31:19
您可能会在计数器字段上放置一个CASE语句吗?
CASE WHEN counter >= 5 THEN 5
WHEN counter >=3 THEN 3
WHEN counter >=1 THEN 1
ELSE 0 END然后将其添加到select和group子句中。
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)发布于 2015-08-03 12:38:19
我正要在行中发布一些关于Kez所做的事情(使用case语句),但有点不同。
我不知道在这里你需要哪些条件,我不知道计数器>= (1,3,5)是否可以被翻译成>= 5?在下面的示例中,我认为计数器>= (1, 3,5 )是指计数器>= 5(问题是如何理解这里的分号--如果要将它们转换为ANDs或or ),我使用了>=,因此计数器>= (1,3,5)与计数器>=5相同,但如果分号被理解为or,则表示您感兴趣的计数器值2或4)。
无论如何,对于不想在max函数中考虑标准化输出的任何条件,请将它们包含在情况条件中,并使计数器返回零,因此它不会影响您的最大值(如果需要,也不影响负数)。
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, counterhttps://stackoverflow.com/questions/31787205
复制相似问题