Подсчет вхождений значения в нескольких столбцах - postgres - PullRequest
0 голосов
/ 24 мая 2018

У меня есть таблица с именем fixtures (я упростил для этого примера), и я хотел бы заполнить последние два столбца (* _plus_mc_per) процентом случаев, произошедших для каждого числа при выполнении запроса к mc_*колонны.Это выглядело бы как пример

#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_plus_mc_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 раза, поскольку он очень неэффективен.Мой SQL-фу не силен и искал способ сделать это за один вызов базы данных, что позволило бы мне тогда взять это процентное значение и обновить столбец процентного отношения

Спасибо

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

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;

FILTER - это стандартный синтаксис ANSI.Преобразование логических чисел в числа является очень удобной конструкцией.

0 голосов
/ 24 мая 2018

Попробуйте это:

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 в вашем запросе, так каквсегда будет истинным.

Если вам нужно количество столбцов * _mc для каждой строки с условием > 0, попробуйте следующее:

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;

ОБНОВЛЕНИЕ:

Расчет one_plus_mc_per

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...