[英]How do I count the rows that are not empty with GROUP BY in Python's SQLite3?
我在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
選擇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,因此如果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)]
AFAIK,您不能僅通過SQL查詢獲得它。 NULL是一種特殊的動物,只能被IS NULL
捕獲,並且絕對與""
。 但這還不是全部: SELECT COUNT GROUP BY
將永遠不會返回計數為0的行,而只會為該組不返回任何行。 畢竟,該組的查詢沒有返回任何行,而count只是返回的lines上的合計。
當然可以使用外部聯接在結果集中強制一行,但是除非您真的精通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}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.