如何通过v_id
获得最大w_cost
,最终结果集应包括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;
窗口函数:
这就是窗口函数的 https://www.postgresql.org/docs/current/static/tutorial-window.html
查看数据库<>小提琴
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
答: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
答:COALESCE
如窗口功能部分所述。
B:排序以首先获取想要的行。
C:DISTINCT ON
第一行的每个不同v_id
过滤器。
下面的 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
w_cost
的值。
为此,我创建了一个名为w_r_cost_table
的临时表。使用"case when",我们可以创建一个 if/else 子句,并将更正后的值放在一个名为w_r_cost
的新列中。
然后,使用 temp 表w_r_cost_table
,我们可以通过使用字段w_r_cost
执行一个组,就像在grouped_table
中所做的那样。
最后,只需在grouped_table
中进行选择即可获得结果。
我在这个例子中使用了Postgres。