我有一个包含这些列的表:
我需要制作一个报告,计算每个“玩家”在player_in字段中的重复次数,如在player_out字段中。 例如,如果我在表中有这两行(按相应的顺序)。
id user_id player_in player_out
1 1 88 56
2 7 77 88
玩家88的结果将是2,而对于玩家56和77,只有1
答案 0 :(得分:3)
使用使用union all
的子查询将两列放入一列,然后使用标准count(*)
:
注意:因此,根据对此答案的评论中的进一步请求,查询包括进出的个别总数。
select
player_id,
count(*) as total,
sum(ins) as ins,
sum(outs) as outs
from (
select
player_in as player_id,
1 as ins,
0 as outs
from mytable
union all
select player_out, 0, 1
from mytable
) x
group by player_id
注意:您必须使用union all
(而不仅仅是union
),因为union
会删除重复项,而union all
则不会。{/ p>
答案 1 :(得分:2)
您可以使用交叉连接到2行虚拟表来取消忽略player_*
列,然后对结果进行分组,如下所示:
SELECT
player,
COUNT(*) AS total_count
FROM (
SELECT
CASE WHEN x.is_in THEN t.player_in ELSE t.player_out END AS player
FROM mytable t
CROSS JOIN (SELECT TRUE AS is_in UNION ALL SELECT FALSE) x
) s
GROUP BY
player
;
也就是说,原始表的每一行基本上都是重复的,并且该行的每个副本都提供player_in
或player_out
,具体取决于派生表的is_in
列是否为{{ 1}}或TRUE
,以形成一个FALSE
列。这种univoting方法可能比UNION方法suggested by @Bohemian表现更好,因为这种方式(物理)表只传递一次(但你需要测试和比较两种方法,以确定这种方法是否有任何实质性的好处在你的特殊情况下)。
要计算进出计数,正如您在上述答案的一条评论中所要求的那样,您可以扩展我的原始建议:
player
如您所见,派生表现在另外返回SELECT
player,
COUNT( is_in OR NULL) AS in_count,
COUNT(NOT is_in OR NULL) AS out_count,
COUNT(*) AS total_count
FROM (
SELECT
x.is_in,
CASE WHEN x.is_in THEN t.player_in ELSE t.player_out END AS player
FROM mytable t
CROSS JOIN (SELECT TRUE AS is_in UNION ALL SELECT FALSE) x
) s
GROUP BY
player
;
列本身,并且该列用于两个条件聚合,用于计算玩家进出的次数。 (如果您有兴趣,可以解释is_in
技巧here。)
您还可以将OR NULL
条目重写为COUNT(condition OR NULL)
。这肯定会缩短这两个表达式,有些人还会发现SUM(condition)
计算更清晰/更优雅的方法。在任何一种情况下,性能都可能没有差异,因此请选择适合您口味的方法。
可以找到第二个查询的SQL小提琴演示here。