SQlite使用不同的“on”语句连接相同的表两次

时间:2012-11-28 17:36:14

标签: sql sqlite join

我找不到我的问题的答案,我不知道我的查询是否正确,这可能是一个SQLite问题,请帮我解决问题。

我的数据库中有两个表:

processTable {id}
taskTable {id, processId, amount, done}

存在多对一关系(一个进程可以分配多个任务)。 “amount”和“done”是提供任务进度信息的整数值。如果“完成”> =“金额”,则完成任务。我需要查询数据库以获得类似的东西:

+---------+-----------+------------+
| process | tasksDone | tasksCount |
+---------+-----------+------------+
| 1       | 1         | 3          |
+---------+-----------+------------+
| 2       | 2         | 5          |
+---------+-----------+------------+

基于我在表格中的数据:

processTable
+----+
| id |
+----+
| 1  |
+----+
| 2  |
+----+

tasksTable
+----+-----------+--------+------+
| id | processId | amount | done |
+----+-----------+--------+------+
| 1  | 1         | 10     | 10   | <- this task is done
+----+-----------+--------+------+
| 2  | 1         | 15     | 5    |
+----+-----------+--------+------+
| 3  | 1         | 80     | 5    |
+----+-----------+--------+------+
| 4  | 2         | 25     | 0    |
+----+-----------+--------+------+
| 5  | 2         | 60     | 60   | <- this task is done
+----+-----------+--------+------+
| 6  | 2         | 30     | 15   |
+----+-----------+--------+------+
| 7  | 2         | 40     | 40   | <- this task is done
+----+-----------+--------+------+
| 8  | 2         | 100    | 50   |
+----+-----------+--------+------+

所以,我写了这个查询:

SELECT processTable.id AS process, 
       COUNT(tasksTableDone.id) AS tasksDone, 
       COUNT(tasksTableAll.id) AS tasksCount 

FROM processTable

LEFT JOIN tasksTable AS tasksTableAll 
     ON   tasksTableAll.processId = processTable.id 

LEFT JOIN tasksTable AS tasksTableDone 
     ON   tasksTableDone.processId = processTable.id 
          AND
          tasksTableDone.done >= tasksTableDone.amount 

但我得到的是:

+---------+-----------+------------+
| process | tasksDone | tasksCount |
+---------+-----------+------------+
| 1       | 3         | 3          |
+---------+-----------+------------+
| 2       | 5         | 5          |
+---------+-----------+------------+

我一次尝试只使用一个连接运行查询,一切运行良好。

仅使用第一次加入进行查询:

SELECT processTable.id AS process,  
       COUNT(tasksTableAll.id) AS tasksCount 

FROM processTable

LEFT JOIN tasksTable AS tasksTableAll 
     ON   tasksTableAll.processId = processTable.id 

Result:
+---------+------------+
| process | tasksCount |
+---------+------------+
| 1       | 3          |
+---------+------------+
| 2       | 5          |
+---------+------------+

仅使用第二次连接查询:

SELECT processTable.id AS process,  
       COUNT(tasksTableDone.id) AS tasksDone 

FROM processTable

LEFT JOIN tasksTable AS tasksTableDone 
     ON   tasksTableDone.processId = processTable.id 
          AND
          tasksTableDone.done >= tasksTableDone.amount 

Result:
+---------+-----------+
| process | tasksDone |
+---------+-----------+
| 1       | 1         |
+---------+-----------+
| 2       | 2         |
+---------+-----------+

如何在一个查询中使用这两个连接以获得正确的结果?我知道我可以使用另一个SELECT而不是JOIN,但我认为它在性能方面会更贵。

1 个答案:

答案 0 :(得分:3)

您可以使用聚合实现CASE语句:

使用SUM()

的版本
SELECT p.id AS process,  
  sum(case when t.amount = t.done then 1 else 0 end) AS tasksDone,
  count(p.id) AS tasksCount
FROM processTable p
LEFT JOIN tasksTable t
  ON t.processId = p.id 
group by p.id

请参阅SQL Fiddle with Demo

使用COUNT()的版本:

SELECT p.id AS process,  
  count(case when t.amount = t.done then 1 else null end) AS tasksDone,
  count(p.id) AS tasksCount
FROM processTable p
LEFT JOIN tasksTable t
  ON t.processId = p.id 
group by p.id

请参阅SQL Fiddle with Demo

编辑,在您的评论之后,您可以将其包装在选择中以获取progress

select process,
  tasksDone,
  tasksCount,
  (tasksDone / tasksCount) progress
from
(
  SELECT p.id AS process,  
    count(case when t.amount = t.done then 1 else null end) AS tasksDone,
    count(p.id) AS tasksCount
  FROM processTable p
  LEFT JOIN tasksTable t
    ON t.processId = p.id 
  group by p.id
) src