我正在使用一个像这样的表:
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进行分组,首先购买,但我宁愿不创建另一个子查询。
答案 0 :(得分:2)
使用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没有“第一”聚合功能,但是效果很好。
答案 1 :(得分:1)
我同意桑德斯。
您需要外部查询。
除了SELECT DISTINCT(实际上可以归结为SELECT列表的所有列)之外,您不能将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
答案 2 :(得分:0)
我猜想PostgreSQL的DISTINCT ON
可以达到目的:
SELECT DISTINCT ON (userid)
userid, eventdate, eventname
FROM "table"
ORDER BY (eventdate);
这将为您提供userid
中每行最少eventdate
的行。
答案 3 :(得分:0)
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;
这应该可以解决问题!您可以在外部查询中使用其他聚合函数,并在子查询中使用其他窗口函数。