Как подсчитать строки, которые не являются пустыми, с помощью GROUP BY в SQLite3 Python? - PullRequest
0 голосов
/ 04 июня 2018

Я использую стандарт SQLite3 в Python 3.6.Я хочу посчитать для каждого group_num, сколько строк имеет запись для list_num, которая не пуста.Пустое значение означает либо пустую строку, либо NULL.

Я в настоящее время группирую с:

SELECT group_num, count(list_num)  
FROM pair_candidates WHERE list_num IS NOT NULL 
GROUP BY group_num

Это подсчитывает, сколько строк имеют одинаковые group_num, но, к сожалению, это не говорит мне о том, каку многих из этих строк есть list_num, который не пуст.

Я попытался добавить WHERE list_num IS NOT NULL перед предложением GROUP BY, и это не помогает.Попытка HAVING list_num IS NOT NULL после того, как GROUP BY также не помогла.

Что мне нужно сделать, чтобы получить мои счета?

Пример:

group_num | list_num
----------+---------
1         | 
1         | 1
2         | 1
2         | 1
3         | ""
3         |

Я хочучтобы получить

group_num | count
----------+------
1         | 1
2         | 2
3         | 0

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

AFAIK, вы не можете получить его просто из запроса SQL.NULL - это специальное животное, которое может быть поймано только IS NULL и определенно не совпадает с "".Но это еще не все: SELECT COUNT GROUP BY никогда не вернет строку с 0 в качестве счетчика, а просто не вернет строку для этой группы.В конце концов, ни одна строка не была возвращена запросом для этой группы, а count - это всего лишь совокупность в возвращаемых строках .

. Конечно, можно использовать внешние объединения для форсирования строки в результатеустановить, но это, безусловно, будет довольно сложно, если вы не очень разбираетесь в SQL.Но смешивать 2 запроса из кода Python тривиально: первый возвращает список групп и инициализирует счетчик 0, второй возвращает ненулевой счет и может использоваться для обновления начального отображения.

Предполагается, чтоcon - активное соединение с базой данных Sqlite3, вы можете сделать:

groups = { x[0]: 0 for x in con.execute(
    "SELECT distinct group_num FROM pair_candidates").fetchall() }
groups.update({ x[0]: x[1] for x in con.execute(
    """SELECT group_num, count(list_num)
    FROM pair_candidates WHERE list_num != ""
    GROUP BY group_num""").fetchall() })
print(groups)

Возвращает, как и ожидалось:

{1: 1, 2: 2, 3: 0}
0 голосов
/ 04 июня 2018

Выберите строки, имеющие list_num , не равный пустой строке.Поскольку сравнение с NULL приводит к UNKNOWN, эти строки также будут отброшены:

SELECT group_num, COUNT(*)
FROM pair_candidates
WHERE list_num != ''
GROUP BY group_num

Но это не даст результатов для group_num , не имеющего строк, соответствующих критериям, поэтому результаты не будутименно то, что вы надеялись.Чтобы подсчитать количество «пустых» групп, вы также можете использовать тот факт, что COUNT(X) возвращает количество раз, когда X не равно NULL в группе.

SELECT group_num, COUNT(NULLIF(list_num, ''))
FROM pair_candidates
GROUP BY group_num

NULLIF(X, Y) возвращает свой первый аргумент, если аргументы различны, NULL, если они одинаковы, поэтому COUNT(NULLIF(X, '')) не считается, если X равно ''.

. Полный пример:

In [1]: from contextlib import closing

In [2]: import sqlite3

In [3]: conn = sqlite3.connect(':memory:')

In [4]: with closing(conn.cursor()) as cur:
   ...:     cur.execute('create table pair_candidates (group_num, list_num)')
   ...:     cur.executemany('insert into pair_candidates values (?, ?)', [
   ...:         (1, None), (1, 1), (2, 1), (2, 1), (3, ""), (3, None)])
   ...:         

In [5]: with closing(conn.cursor()) as cur:
   ...:     cur.execute('''select group_num, count(nullif(list_num, ''))
   ...:                    from pair_candidates
   ...:                    group by group_num''')
   ...:     res = cur.fetchall()
   ...:     

In [6]: res
Out[6]: [(1, 1), (2, 2), (3, 0)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...