Sql 计算多列中某个值的出现次数-postgres
我有一个名为Sql 计算多列中某个值的出现次数-postgres,sql,postgresql,Sql,Postgresql,我有一个名为fixtures(本例中我已经简化了)的表,并希望通过对mc*列运行查询来填充最后两列(*\u加上\u mc\u per)中每个数字发生的时间百分比。它将像这样作为一个例子 #mc = Match Corner # mc_per = Match Corner Percentage | mc_0 | mc_1 | mc_3 | mc_4 | match_count | one_plus_mc_per | two_plus_mc_per | | 1 | 4 | 3 |
fixtures
(本例中我已经简化了)的表,并希望通过对mc*
列运行查询来填充最后两列(*\u加上\u mc\u per)中每个数字发生的时间百分比。它将像这样作为一个例子
#mc = Match Corner # mc_per = Match Corner Percentage
| mc_0 | mc_1 | mc_3 | mc_4 | match_count | one_plus_mc_per | two_plus_mc_per |
| 1 | 4 | 3 | null | 3 | 100 | 66 |
在我运行查询时,它看起来像
#mc = Match Corner # mc_per = Match Corner Percentage
| mc_0 | mc_1 | mc_3 | mc_4 | match_count | one_plus_mc_per | two_plus_mc_per |
| 1 | 4 | 3 | null | 3 | null | null |
因此,从查询one\u加\u mc\u per
开始,我可以这样做
SELECT COUNT(*) FROM fixtures WHERE coalesce(mc_0,0) >= 1 AND id = 182;
# Using coalesce for dealing with null, will return a 0 if value null
这是回报
| count |
| 1 |
如果我对每一列单独运行这个查询,返回的结果将是
| count | count | count | count |
| 1 | 1 | 1 | 0 |
因此,我可以将所有列值相加,然后除以匹配计数。这是有道理的(我感谢dmfay让我在前面的问题中思考他的建议)
我的问题是我不能运行这个查询4次,例如,因为这是非常无效的。我的SQLFU不强,正在寻找一种方法,通过对数据库的一次调用来实现这一点,使我能够获取该百分比值并更新百分比列
谢谢试试这个:
SELECT
SUM(CASE WHEN coalesce(mc_0,0) >= 1 THEN 1 ELSE 0 END) count_0,
SUM(CASE WHEN coalesce(mc_1,0) >= 1 THEN 1 ELSE 0 END) count_1,
SUM(CASE WHEN coalesce(mc_3,0) >= 1 THEN 1 ELSE 0 END) count_3,
SUM(CASE WHEN coalesce(mc_4,0) >= 1 THEN 1 ELSE 0 END) count_4,
FROM
fixtures
WHERE id = 182;
它将返回单个查询中所有列的计数
但是我不确定,在你的查询中,id=id
有什么用,因为它总是正确的
如果您想对>0
条件下的每一行计算列数*\u mc,请尝试以下操作:
SELECT
(CASE WHEN coalesce(mc_0,0) >= 1 THEN 1 ELSE 0 END +
CASE WHEN coalesce(mc_1,0) >= 1 THEN 1 ELSE 0 END +
CASE WHEN coalesce(mc_3,0) >= 1 THEN 1 ELSE 0 END +
CASE WHEN coalesce(mc_4,0) >= 1 THEN 1 ELSE 0 END) as count
FROM
fixtures
WHERE id = 182;
更新:
计算<代码>一个加上每个<代码>
SELECT
CAST((CASE WHEN coalesce(mc_0,0) >= 1 THEN 1 ELSE 0 END +
CASE WHEN coalesce(mc_1,0) >= 1 THEN 1 ELSE 0 END +
CASE WHEN coalesce(mc_3,0) >= 1 THEN 1 ELSE 0 END +
CASE WHEN coalesce(mc_4,0) >= 1 THEN 1 ELSE 0 END)AS DECIMAL)/match_count as one_plus_mc_per
FROM
fixtures
WHERE id = 182;
Postgres有很好的能力来回答这类问题:
SELECT COUNT(*) FILTER (WHERE mc_0 >= 1) as count_0,
COUNT(*) FILTER (WHERE mc_1 >= 1) as count_1,
COUNT(*) FILTER (WHERE mc_3 >= 1) as count_3,
COUNT(*) FILTER (WHERE mc_4 >= 1) as count_4,
AVG ( (mc_0 >= 1)::int + (mc_1 >= 1)::int + (mc_3 >= 1)::int + (mc_4 >= 1)::int
) as one_plus_mc_per
FROM fixtures
WHERE id = 182;
过滤器是ANSI标准语法。布尔数到数字的转换是一种非常方便的构造。您可能可以在不同的窗口上使用窗口函数。在rextester或db fiddle中构建env以消除干扰,您可以用fixtures
表的结构和内容的更多细节更新问题吗。@HaleemurAli当然可以,但您想知道什么?我不明白一加一mc_per是100,二加一mc_per是66。谢谢@RahulJain,id的字面意思是指fixture的id,我已经更新了这个问题。这正是我想要的,非常感谢。我想我可以接受这个返回值,然后用另一个查询除以匹配计数,或者在同一个查询中也可以这样做?很乐意帮助。如果答案满足您的要求,请接受。可以,只需等待足够的时间即可:-)。。。。你对我上面的问题有什么想法吗?我没想到你会在这里。你是如何计算每个人一个加上一个mc的?示例会有所帮助。它将是计数结果除以列match\u count
Thank you Gordon,我也会看看这个,上面的答案有什么不同吗?@Richlewis<代码>过滤器
效率更高。布尔-->整数转换的使用无疑简化了代码。