我使用的表看起来像这样:
userID, eventDate, eventName
1 2019-01-01 buySoup
2 2019-01-01 buyEggs
2 2019-01-03 buyMilk
2 2019-01-04 buyMilk
3 2019-01-02 buyBread
3 2019-01-03 buyBread
我目前的查询是:
SELECT
userID,
FIRST_VALUE(eventName) OVER (
PARTITION BY userID ORDER BY eventDate ASC
) AS firstBought
FROM table
GROUP BY userID
我觉得这应该回归:
userID, firstBought
1 buySoup
2 buyEggs
3 buyBread
相反,它给出了错误:
'错误:列“table.eventName”必须出现在GROUP BY子句中或用于聚合函数中
有没有办法获取此值而不将其包含在按功能分组或创建子查询?我正在使用PostgreSQL。
如果我将它包含在group by子句中,则返回
userID, firstBought
1 buySoup
2 buyEggs
2 buyEggs
2 buyEggs
3 buyBread
3 buyBread
我知道我可以使它成为子查询,然后按userID,firstBought进行分组,但我宁愿不创建另一个子查询。
而不是group by
,使用select distinct
:
select distinct userID,
FIRST_VALUE(eventName) over (partition by userID order by eventDate ASC) as firstBought
from table ;
或者,您可以使用数组:
select userId,
(array_agg(eventName order by eventDate))[1] as firstBought
from table
group by userId;
Postgres没有“第一”聚合功能,但这种方法效果很好。
我同意A. Saunders。
你需要一个外部查询。
除了SELECT DISTINCT(实际上归结为SELECT列表的所有列的GROUP BY)之外,您不能将OLAP和GROUP BY函数混合到同一个SELECT中。
所以,如果你有MAX(),你必须:
WITH -- your input data ...
input(userID,eventDate,eventName) AS (
SELECT 1,DATE '2019-01-01','buySoup'
UNION ALL SELECT 2,DATE '2019-01-01','buyEggs'
UNION ALL SELECT 2,DATE '2019-01-03','buyMilk'
UNION ALL SELECT 2,DATE '2019-01-04','buyMilk'
UNION ALL SELECT 3,DATE '2019-01-02','buyBread'
UNION ALL SELECT 3,DATE '2019-01-03','buyBread'
)
,
getfirstbought AS (
SELECT
userid
, eventdate
, FIRST_VALUE(eventname) OVER (
PARTITION BY userid ORDER BY eventdate
) AS firstbought
FROM input
)
SELECT
userid
, firstbought
, MAX(eventdate) AS maxdt
FROM getfirstbought
GROUP BY 1,2;
-- out userid | firstbought | maxdt
-- out --------+-------------+------------
-- out 2 | buyEggs | 2019-01-04
-- out 3 | buyBread | 2019-01-03
-- out 1 | buySoup | 2019-01-01
-- out (3 rows)
-- out
-- out Time: First fetch (3 rows): 22.157 ms. All rows formatted: 22.208 ms
我猜PostgreSQL的DISTINCT ON
可以做到这一点:
SELECT DISTINCT ON (userid)
userid, eventdate, eventname
FROM "table"
ORDER BY (eventdate);
这将给你每userid
的行与最小eventdate
。
FIRST_VALUE
不是一个集合函数。它是一个分析窗函数。所以你的基本查询不需要GROUP BY
子句。它应该重写为:
SELECT
userID,
FIRST_VALUE(eventName) over (PARTITION BY userID ORDER BY eventDate ASC) AS firstBought
FROM table;
从上面的一条评论中可以看出,您正在使用的其他功能包括MAX
等聚合函数。要完成您要执行的操作,您需要将上述查询用作子查询。这将允许您使用聚合函数并从基本查询中获取唯一值。查询看起来像这样(我添加了一个价格列作为例子)。
SELECT userID, firstBought, MAX(price)
FROM (
SELECT userID, price, FIRST_VALUE(eventName) over (partition by userID order by eventDate ASC) as firstBought
from test
) x
GROUP BY userId, firstBought;
这应该做的伎俩!您可以在外部查询上使用其他聚合函数,并在子查询中使用其他窗口函数。