2012-11-28 32 views
2

我无法找到我的问题的答案,并且我不知道我的查询是否正确,并且这可能是SQLite问题,请帮我解决问题。SQlite使用不同的“on”语句连接两次相同的表

我在我的数据库中的两个表:

processTable {id} 
taskTable {id, processId, 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   | 
+---------+-----------+ 

如何使用这两加入一个查询中得到正确的结果?我知道,不是JOIN,我可以使用另一个SELECT,但我认为它在性能意义上会更昂贵。

回答

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 
+2

您可以使用SQLite/MySQL的功能,TRUE = 1,FALSE = 0。因此'总和( case when t.amount = t.done then 1 else 0 end)'与sum(t.amount = t.done)相同' –

+0

@ypercube感谢那些信息,我不知道。我通常不在MySQL或SQLite中工作。 – Taryn

+0

这太棒了!它的功能就像魅力一样,但还有一个问题:因为您不使用JOIN,所以不能添加包含计算的进度值的另一列,例如:SELECT ...(tasksDone/tasksCount)AS progress' - 针对这个问题的解决方案? – Darrarski

相关问题