2

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

我的数据库中有两个表:

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

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

+---------+-----------+------------+
| 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,但我认为它在性能方面会更昂贵。

4

1 回答 1

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

版本使用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

编辑,在您发表评论后,您可以将其包装在一个选择中以获得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
于 2012-11-28T17:50:54.913 回答