我希望使用 null 值连接四个表而不重复,然后将其转换为SQLAlchemy查询。
表格(简化):
Category(id, name)
Task(id, category.id, name)
User(id, name)
还有一个多对多的表格:
Solved(task.id, user.id)
我希望获得包含其类别的所有任务以及具有解决任务的特定用户的列:
+---------------+-----------+-----------+
| category.name | task.name | user.name |
+---------------+-----------+-----------+
| abc | abctask1 | <null> |
| abc | abctask2 | luke |
| def | deftask1 | <null> |
| ghi | ghitask1 | <null> |
| ghi | ghitask2 | luke |
+---------------+-----------+-----------+
目前我有3到4个单独的SQLAlchemy查询来执行该任务。如果可能的话,它应该只合并到一个查询中,以避免对数据库进行过多的读取。
到目前为止,我已经:
SELECT DISTINCT
cat.name, t.name, u.name
FROM
Task t
JOIN
Category cat ON cat.id = t.category_id
LEFT JOIN
Solved s ON s.task_id = t.id
LEFT JOIN
User u ON s.user_id = u.id AND
u.name = 'luke'
ORDER BY
cat.name
但是,虽然DISTINCT
,我从给定用户的所有行中得到了重复:
+---------------+-----------+-----------+
| category.name | task.name | user.name |
+---------------+-----------+-----------+
| abc | abctask1 | <null> |
| abc | abctask2 | luke |
| abc | abctask2 | <null> | <-- duplicate
| def | deftask1 | <null> |
| ghi | ghitask1 | <null> |
| ghi | ghitask2 | luke |
| ghi | ghitask2 | <null> | <-- duplicate
+---------------+-----------+-----------+
是否有可能通过一个查询获取此表并将其转换为SQLAlchemy?
答案 0 :(得分:1)
问题来自你的数据,即你可能有2个任务叫做abctask2 / ghitask2。也许你应该对taskname设置一个约束。您的查询效果很好。
http://sqlfiddle.com/#!9/c4647c/4
尝试检查
SELECT category_id, name ,count(*) from TASK GROUP BY category_id, name HAVING COUNT(*)<>1
答案 1 :(得分:1)
您有两个LEFT JOINS
:
solved
连接到多个行。说,&#39; jane&#39;和&#39;卢克&#39;解决了这个任务。您仍然可以 行,&#39; jane&#39;如果没有显示,连接条件会将她过滤掉,但LEFT JOIN
仍保留结果中的行并附加NULL值。
您可以使用括号和[INNER] JOIN
代替LEFT JOIN
和solved
之间的users
来实现您的目标。 The manual:
如有必要,请使用括号来确定嵌套顺序。在里面 没有括号,
JOIN
从左到右的巢。
SELECT c.name AS cat_name, t.name AS task_name, u.name AS user_name
FROM task t
JOIN category c ON cat.id = t.category_id
LEFT JOIN
(solved s JOIN users u ON u.id = s.user_id AND u.name = 'luke') ON s.task_id = t.id
ORDER BY 1, 2, 3;
使用表名users
代替保留字 。user
假设users.name
已定义为唯一,或者您可以将多个用户命名为&#39; luke&#39;。
如果(task.id, users.id)
中的solved
定义为UNIQUE
或PRIMARY KEY
,则根本不需要DISTINCT
。
结果查询不仅正确,而且速度更快。
以上查询的SqlAlchemy版本:(contributed by @van)
这假定Category
,Task
和User
是映射类,而solved
是Table
的实例(只是一个关联表,如代码示例{{ 3}}):
user_name = 'luke'
q = (session.query(Category.name, Task.name, User.name)
.select_from(Task)
.join(Category)
.outerjoin(
join(solved, User,
(solved.c.user_id == User.id) & (User.name == user_name),
))
.order_by(Category.name, Task.name, User.name)
)