簡體   English   中英

如何在Python的SQLite3中使用GROUP BY計算不為空的行?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM