我发现准确地说出这个问题有点困难。
所以,为了简化:我有两个表,称之为event_type
和player_events
。第一个表是事件类型(字符串)列表,调用列event_type.name
。
player_events
是各个玩家事件的列表。某些玩家可能会丢失某些事件,并且同一玩家可能会多次发生事件。因此,player_events
具有相关列player_events.player_id
和player_events.event_type_name
,以及处理创建时间等的其他列,但后者无关紧要。
我想要一个玩家事件类型计数,包括零。我需要区分每个玩家的不同事件类型。所以最后我应该得到这样的东西:
player_id event_type_name player_event_count
0 LoginEvent 1
0 ProfileChangedEvent 0
1 LoginEvent 5
1 ProfileChangedEvent 1
...
我在考虑将event_type
表格加入player_events
表并以某种方式对player_events.player_id
和player_events.event_type_name
进行分组,但我无法将其转到工作
类似于此的东西错过了零:
select player_id, event_type_name, count(event_type_name) as player_event_count
from player_events
group by player_id, event_type_name
这样的事情怎么做得最好?
答案 0 :(得分:0)
如果您有一个PLAYER
表(PLAYER_EVENT_TYPES
的父级,其中PLAYER_ID
是主键),那么这样做的好方法是:
select p.player_id, et.event_type_name, count(*) as player_event_count
from event_type et
cross join players p
left join player_events pe on pe.player_id = p.player_id and pe.event_type_name = et.event_type_name
group by p.player_id, et.event_type_name;
PLAYER
表... 由于您没有PLAYER
表,您可以这样做,而不是:
SELECT pe.player_id,
et.event_type_name,
COUNT (CASE WHEN pe.event_type_name = et.event_type_name THEN 1 ELSE NULL END) cnt
FROM player_events pe CROSS JOIN event_types et
GROUP BY pe.player_id, et.event_type_name
ORDER BY pe.player_id, et.event_type_name
(对不起,我不知道“HIVE”你必须在该数据库中使用等效的CASE
。)
我更喜欢拥有PLAYER
表,因为这对我来说不太清楚。
答案 1 :(得分:0)
我实际上更喜欢九十年代早期可能的风格 - 在CASE WHEN条款可用之前:
这里的诀窍是在一个(临时)表中获取所有可能的player_id
- s,在另一个表中获取所有event_type_name
- s,并将CROSS JOIN连接在一起,最后LEFT JOIN到player_events
表。然后计算来自event_type_name
表的player_events
- s。 event_type_name
的NULL出现只是不计算。
如果您可以依赖player_id
中所有event_type_name
- 和所有player_events
- s的事实,那么您可以这样做:
WITH
-- input data for player_events, don't use in query
player_events(player_id,tm,event_type_name) AS (
SELECT 0,TIME '00:01:01','LoginEvent'
UNION ALL SELECT 1,TIME '00:01:12','LoginEvent'
UNION ALL SELECT 1,TIME '00:01:12','LoginEvent'
UNION ALL SELECT 1,TIME '00:01:12','LoginEvent'
UNION ALL SELECT 1,TIME '00:01:12','LoginEvent'
UNION ALL SELECT 1,TIME '00:01:12','LoginEvent'
UNION ALL SELECT 1,TIME '00:01:12','ProfileChangedEvent'
)
-- real query starts here - replace the comma below with WITH
,
-- all distinct player_id-s from player_events
players AS (
SELECT DISTINCT player_id FROM player_events
)
,
-- all distinct event_type_name-s from player_events
all_event_types AS (
SELECT DISTINCT event_type_name FROM player_events
)
SELECT
p.player_id
, a.event_type_name
, COUNT(e.event_type_name) AS player_event_count
FROM players p
CROSS JOIN all_event_types a
LEFT JOIN player_events e USING(player_id,event_type_name)
GROUP BY
p.player_id
, a.event_type_name
ORDER BY
p.player_id
;
如果有player_id
- s或event_type_name
- s在player_events
表中没有任何条目,则必须为player_id
创建一个SELECT - s和event_type_name
- 保证返回所有可能的事件,并替换我使用的那些SELECT DISTINCT。
马