Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 计算多列中某个值的出现次数-postgres_Sql_Postgresql - Fatal编程技术网

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<代码>过滤器
效率更高。布尔-->整数转换的使用无疑简化了代码。