如何通过w_cost
获得v_id
的最大值,并且最终结果集应包括av_id
。
s_id sg_id r_cost w_cost av_id v_id
123 100 0.50 1.00 1 333
123 105 0.75 0.50 2 333
123 330 2.00 Null 3 888
如果w_cost
为NULL,则应使用r_cost
。最终结果应该是:
s_id v_id w_cost av_id
123 333 1.00 1
123 888 2.00 3
基本查询是
SELECT
t.s_id,
sv.v_id,
sv.w_cost,
CASE
WHEN sv.w_cost IS NULL THEN
sv.r_cost::numeric
ELSE sv.w_cost::numeric
END AS cost
FROM test t
INNER JOIN stra_ven sv tmad ON
t.s_id = sv.s_id
GROUP BY t.s_id,sv.v_id,sv.w_cost;
答案 0 :(得分:1)
窗口功能:
这是为https://www.postgresql.org/docs/current/static/tutorial-window.html做的窗口功能
请参见db<>fiddle
SELECT
s_id, v_id, w_cost, av_id
FROM
(SELECT
s_id,
v_id,
av_id,
COALESCE(w_cost, r_cost) as w_cost, -- A
MAX(COALESCE(w_cost, r_cost)) OVER (PARTITION BY v_id) as max_w_cost -- B
FROM testdata) s
WHERE
max_w_cost = w_cost -- C
A:COALESCE
给出列表中的第一个非NULL
值。因此,如果w_cost
是NULL
,则将使用r_cost
。
B:窗口函数MAX()
给出v_id
分区中的最大值。 max函数使用与(A)中相同的COALESCE
子句
C:WHERE
子句过滤行,其中max等于w_cost
的当前值。
在我的示例中,如果还有更多行具有相同的MAX
值,则将所有行都包含在内。如果只需要其中之一,则可以在分区中添加一列,以使窗口更加精确。或者,您也可以按顺序订购某商品,然后选择第一个,或者按DISTINCT ON
或多或少地选择一个。
区别开:
使用DISTINCT ON
可以过滤特殊行的不同行(而普通DISTINCT
会查看所有列)。由于没有任何ORDER BY
子句的结果集可能是非常随机的,因此应按v_id和最终成本(最优先(DESC
)进行排序;如上所述,使用COALESCE
函数进行计算)。然后DISTINCT
进入第一行。
SELECT DISTINCT ON (v_id) -- C
s_id, v_id, cost as w_cost, av_id
FROM
(SELECT
s_id,
v_id,
av_id,
COALESCE(w_cost, r_cost) as cost -- A
FROM testdata
ORDER BY v_id, cost DESC) s -- B
A:COALESCE
,如窗口功能部分所述。
B:命令先获取想要的行。
C:DISTINCT ON
为第一行中的每个v_id
进行过滤。
答案 1 :(得分:0)
以下SQL可能有效:
with my_table as (
select
123 as s_id,
100 as sg_id,
0.50 as r_cost,
1.00 as w_cost,
1 as av_id,
333 as v_id
union all
select
123 as s_id,
105 as sg_id,
0.75 as r_cost,
0 as w_cost,
2 as av_id,
333 as v_id
union all
select
123 as s_id,
330 as sg_id,
1.00 as r_cost,
Null as w_cost,
3 as av_id,
888 as v_id
),
w_r_cost_table as (
select t.*,
case
when t.w_cost is not null then t.w_cost
else t.r_cost
end as w_r_cost
from my_table t
),
grouped_table as (
select
A.v_id,
max(A.w_r_cost) as w_cost
from w_r_cost_table A
group by A.v_id
)
select
(select t.s_id from w_r_cost_table t where t.w_r_cost = g.w_cost and t.v_id = g.v_id) as s_id,
g.v_id,
g.w_cost,
(select t.av_id from w_r_cost_table t where t.w_r_cost = g.w_cost and t.v_id = g.v_id) as av_id
from grouped_table g
我们假设临时表my_table
是您的源表。
首先,我们应该为w_cost
列定义更正的值。如您所提,我们不应该考虑null
的{{1}}值。
为此,我创建了一个名为w_cost
的临时表。使用“ case when”,我们可以创建一个if / else子句,并将更正后的值放在一个名为w_r_cost_table
的新列中。
然后,使用临时表w_r_cost
,我们可以使用字段w_r_cost_table
进行分组,就像在w_r_cost
中一样。
最后,只需在grouped_table
中进行选择即可获得结果。
在此示例中,我使用了Postgres。