我有一个像这样的数据集,其中有些行很有用,但已损坏。
create table pages (
page varchar,
cat varchar,
hits int
);
insert into pages values
(1, 'asdf', 1),
(1, 'fdsa', 2),
(1, 'Apples', 321),
(2, 'gwegr', 30),
(2, 'hsgsdf', 2),
(2, 'Bananas', 321);
我想知道每个页面的正确类别以及总点击次数。正确的类别是命中率最高的类别。 我想要一个像:
这样的数据集page | category | sum_of_hits
-----------------------------
1 | Apples | 324
2 | Bananas | 353
我能得到的最远的是:
SELECT page,
last_value(cat) over (partition BY page ORDER BY hits) as category,
sum(hits) as sum_of_hits
FROM pages
GROUP BY 1, 2
但这是错误的:ERROR: column "pages.hits" must appear in the GROUP BY clause or be used in an aggregate function Position: 83
。
我尝试将命中汇总到一个聚合 - ORDER BY max(hits)
,但这没有意义,也不是我想要的。
答案 0 :(得分:1)
在派生表(FROM子句中的子查询)中使用窗口函数first_value()
而不是hits
的颠倒顺序:
select
page,
category,
sum(hits) as sum_of_hits
from (
select
page,
first_value(cat) over (partition by page order by hits desc) as category,
hits
from pages
) s
group by 1, 2
order by 1;
答案 1 :(得分:1)
这里有两个问题:
首先是last_value的用法。请阅读Postgres documentation中有关最后一个值的说明:
请注意,first_value,last_value和nth_value仅考虑 "窗口框架内的行",默认情况下包含行 从分区的开始到当前的最后一个对等体 行。这可能会给nth_value和.n带来无益的结果 特别是last_value。您可以将框架重新定义为整体 通过在UNBOUNDED PRECEDING和UNBOUNDED之间添加ROWS进行分区 遵循OVER条款。有关更多信息,请参见第4.2.8节。
我建议您将其转换为first_value:
SELECT page,
first_value(cat) over (partition BY page ORDER BY hits DESC) as category,
hits
FROM pages
第二个问题是你不能直接在GROUP BY子句中使用window函数,你需要使用子查询或cte:
select page, category,
sum(hits)
from (
SELECT page,
first_value(cat) over (partition BY page ORDER BY hits DESC) as category,
hits
FROM pages
) a
GROUP BY 1, 2
答案 2 :(得分:0)
使用子查询:
{{1}}
答案 3 :(得分:0)
您似乎想要将命中总和和放在最大值。这很容易:
select page, sum(hits) as total_hits,
max(case when seqnum = 1 then category end) as category
from (select p.*,
row_number() over (partition by page order by hits desc) as seqnum
from pages p
) p
group by page;