Python / Sqlite3:使用 GROUP_CONCAT 左连接

Posted

技术标签:

【中文标题】Python / Sqlite3:使用 GROUP_CONCAT 左连接【英文标题】:Python / Sqlite3: LEFT JOIN with GROUP_CONCAT 【发布时间】:2017-11-28 10:14:46 【问题描述】:

我有 2 张桌子:

Tasks:                     Predecessors:

ID | Task | Team           ID | TaskID | PredecessorID
---+------+------          ---+--------+--------------
1  | A    | 1              1  | 1      | None
2  | B    | 1              2  | 2      | 1 
3  | C    | 2              3  | 3      | 1
4  | D    | 2              4  | 3      | 2
                           5  | 4      | None

我想选择团队 2 中的所有任务,并以该形式添加 每个任务的前任,用逗号分隔

ID | Task | Team | Predecessors
---+------+------+-------------
3  | C    | 2    | 1, 2
4  | D    | 2    | None

因此我使用以下 SQL 查询:

SELECT Tasks.*, GROUP_CONCAT(Predecessors.PredecessorID)
FROM Tasks LEFT JOIN Predecessors ON Tasks.ID = Predecessors.TaskID 
WHERE Tasks.Team = 2 GROUP BY Predecessors.TaskID

返回:

ID | Task | Team | Predecessors
---+------+------+-------------
3  | C    | 2    | 1, 2

我该怎么做才能获得无值的行?

这是我的测试代码:

# -*- coding: utf-8 -*-

import sqlite3


con = sqlite3.connect('test.db')
cur = con.cursor()

# Drop old tables if they already exits and create new ones. (For testing).
cur.execute("""DROP TABLE IF EXISTS Tasks""")
cur.execute("""DROP TABLE IF EXISTS Predecessors""")

# Create tables.
cur.execute("""CREATE TABLE Tasks (ID INTEGER PRIMARY KEY AUTOINCREMENT, 
               Task TEXT, Team INTEGER)""")
cur.execute("""CREATE TABLE Predecessors (ID INTEGER PRIMARY KEY AUTOINCREMENT,
               TaskID INTEGER, PredecessorID INTEGER)""")

# Insert some values.
sql = """INSERT INTO Tasks (Task, Team) VALUES (?, ?)"""
for task in [('A', 1), ('B', 1), ('C', 2), ('D', 3)]:
    cur.execute(sql, task)

sql = """INSERT INTO Predecessors (TaskID, PredecessorID) VALUES (?, ?)"""
for predecessor in [(1, None), (2, 1), (3, 1), (3, 2), (4, None)]:
    cur.execute(sql, predecessor)

con.commit()

sql = """SELECT Tasks.*, GROUP_CONCAT(Predecessors.PredecessorID)
FROM Tasks LEFT JOIN Predecessors ON Tasks.ID = Predecessors.TaskID 
WHERE Tasks.Team = 2 GROUP BY Predecessors.TaskID"""
cur.execute(sql)
data = cur.fetchall()
print data

con.close()

感谢您的帮助!

【问题讨论】:

【参考方案1】:

问题是GROUP BY Predecessors.TaskID;对于没有匹配的行,所有 Predecessors 列都是 NULL。

只需改用GROUP BY Tasks.ID

【讨论】:

谢谢!你介意给我写下整个查询吗? (因为我以前从未使用过 GROUP BY 语句,也不知道将它放在我的查询中的确切位置) 替换就行了。 对不起,我没有仔细阅读您的回答。我认为我应该使用 GROUP BY 语句而不是 GROUP_CONCAT。那是垃圾。 GROUP BY 语句解决了我的实际问题!而 obgnaws 的答案也是正确的。【参考方案2】:

你应该仔细检查你的代码。你的sql没有错,你只是写错了测试数据。

your test data[('A', 1), ('B', 1), ('C', 2), ('D', 3)]
and it should be [('A', 1), ('B', 1), ('C', 2), ('D', 2)]

【讨论】:

哦,对了!对不起。当我按照您的预期更正代码时它起作用了!

以上是关于Python / Sqlite3:使用 GROUP_CONCAT 左连接的主要内容,如果未能解决你的问题,请参考以下文章

SQLite3 of python

Python + sqlite3:使用“构造”值执行许多

python-简单的sqlite3使用

python sqlite3

使用 `executemany` 更新现有 SQLite3 数据库中的条目(使用 Python sqlite3)

python sqlite3的问题