2012-03-29 65 views
0

我有来自测试的数据,有两个部分的列表,分别叫做进入和退出。我需要在最后一次测试的部分进入但没有出来的时候为每个部分选择测试值的总和。mysql通过比较两个关系来选择行的总和

IN LIST     OUT LIST     TEST 
+--------+-----------+ +--------+------------+ +------+-------+ 
| testid | in_partid | | testid | out_partid | | test | value | 
+--------+-----------+ +--------+------------+ +------+-------+ 
|  1 |  10 | |  1 |   10 | | 1 |  1 | 
|  1 |  20 | |  1 |   20 | | 2 | 10 | 
|  2 |  10 | |  2 |   10 | | 3 | 100 | 
|  2 |  20 | |  |   | |  |  | 
|  3 |  10 | |  3 |   10 | |  |  | 
|  3 |  20 | |  3 |   20 | |  |  | 
+--------+-----------+ +--------+------------+ +------+-------+ 

SUM是非常简单的,但我可以把它限制在哪里testid比testid更大的最后检查,其中一部分去了,但没有掉那些行?

在本例中,第10部分应汇总所有三个测试值,因为它包含在所有列表中,但第20部分应该只返回测试3的值,如在测试2中它不包含在入出列表中。

partid sum(value) 
    10  111 
    20  100 

我可以使用mysql吗,还是我需要包含php的混合?

+1

嵌套的SQL查询或PHP。我更喜欢第二个,因为第一个可能会很慢。 – kirilloid 2012-03-29 07:55:01

+0

我会遍历每个partid以检查它们是否包含在列表中。我想不出一个可以检查所有可能性的mysql查询。我也认为你是一个例子,因为当2-20会出现在列表中时会发生什么,但是2-10不是?您可能需要获得相同的输出,但mysql查询需要完全不同。 – Martin 2012-03-29 08:24:22

+0

感谢您的意见。也许我会遍历这些部分,用一个空LEFT OUTER JOIN获得最后一个不匹配的测试,然后从那里继续。 – Juhani 2012-03-29 08:58:09

回答

1

我认为你的示例输出在你的逻辑中是不正确的。我认为PARTID 20应该返回101,因为它是存在于列出了两个测试1和3。假设我就在这,这个查询应该返回了预期的效果

SELECT in_partid,SUM(value) 
FROM (
    SELECT DISTINCT in_partid,inl.testid 
    FROM in_list inl 
    INNER JOIN out_list outl ON in_partid=out_partid AND inl.testid=outl.testid 
    ) as tests_passed 
    INNER JOIN tests ON tests_passed.testid=test 
GROUP BY in_partid 

编辑:基于OP的评论我的以上假设是错误的,并且实际上是一项要求。因此,我认为这是一个查询,我认为它符合要求:

SELECT tests_passed.in_partid,SUM(value) 
FROM (
    SELECT DISTINCT inl.in_partid,IFNULL(last_failed_test,0) as last_failed_test 
    FROM in_list inl LEFT JOIN (
     SELECT in_partid,MAX(inl.testid) as last_failed_test 
     FROM in_list inl 
     LEFT JOIN out_list outl ON in_partid=out_partid AND inl.testid=outl.testid 
     WHERE outl.testid IS NULL 
     GROUP BY in_partid 
    ) AS last_passed 
    ON inl.in_partid=last_passed.in_partid 
) as tests_passed 
INNER JOIN tests ON tests_passed.last_failed_test<test 
GROUP BY tests_passed.in_partid 

这将返回上面给出的示例结果的示例数据提供。

+0

不,这是正确的。我只对“异常”后的结果感兴趣。优雅的建议,但不幸的是,这不是我所需要的。谢谢,不过。 – Juhani 2012-03-29 08:55:19

+0

@Juhani好吧,我已经更新了我的答案来处理这个要求。 – liquorvicar 2012-03-30 05:41:33

+0

完美地工作。你是一个巫师! – Juhani 2012-04-10 08:34:36