我在Python 3.6中使用标准的SQLite3。我想计算每个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
不是空的。
我尝试在GROUP BY子句之前添加WHERE list_num IS NOT NULL
,但这没有帮助。在GROUP BY之后尝试HAVING list_num IS NOT NULL
也没有帮助。
我需要做些什么来计算我的数量?
示例:
group_num | list_num
----------+---------
1 |
1 | 1
2 | 1
2 | 1
3 | ""
3 |
我想要
group_num | count
----------+------
1 | 1
2 | 2
3 | 0
答案 0 :(得分:1)
选择 list_num 不等于空字符串的行。因为与NULL的比较产生UNKNOWN,所以这些行也将被丢弃:
SELECT group_num, COUNT(*)
FROM pair_candidates
WHERE list_num != ''
GROUP BY group_num
但这不会产生没有符合条件的行的COUNT(X)
返回组中X不为NULL的次数这一事实。
SELECT group_num, COUNT(NULLIF(list_num, ''))
FROM pair_candidates
GROUP BY group_num
如果参数不同, NULLIF(X, Y)
将返回其第一个参数,如果它们相同则返回NULL,因此如果X为COUNT(NULLIF(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)]
答案 1 :(得分:1)
AFAIK,您无法从SQL查询中获取它。 NULL是一种特殊的动物,只能被IS NULL
捕获,绝对不能与""
相同。但这不是全部:SELECT COUNT GROUP BY
将永远不会返回0作为计数的行,但只会返回该组的无行。毕竟,该组的查询没有返回任何行,而count只是返回行上的聚合 。
当然可以使用外部联接在结果集中强制一行,但除非你真的精通SQL,否则它肯定会相当复杂。但是从Python代码混合2个查询是微不足道的:首先返回组列表并将计数初始化为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}