从隐式JOIN返回行,其中结果存在于两个表中或仅存在于一个表中

时间:2011-12-01 21:15:42

标签: postgresql select

我有一个管理自动化测试环境的PostgreSQL-9.0.x数据库。有许多表包含名为“buildlist”和&的各种静态数据(操作系统版本,测试名称等)。 'osversmap'。但是,还有两个表包含经常更改的数据。第一个是“挂起”表,它实际上是一个测试队列,其中测试系统自行选择待测试,然后在测试运行完成时删除。第二个是“结果”表,其中包含生成(正在进行和完成)的测试结果。

挂起表中的记录与结果表中的记录具有一对多的关系(挂起中的每一行在结果中可以有0行或更多行)。例如,如果没有测试系统自行分配挂起的行,则结果中将关联的行为零,然后一旦指定挂起的行,结果中的行数将针对每个挂起的行增加。另外一个问题是,我总是只想要与每个挂起的表行关联的最新结果表行。我需要做的是查询“pending”表中的待处理测试,然后从结果表中获得与每个待处理表行对应的“logurl”。

所有这一切都与这个问题非常相似,只不过我增加了两个额外的表与静态数据(buildlist& osversmap)的负担: PHP/SQL: Using only one query, SELECT rows from two tables if data is in both tables, or just SELECT from one table if not

我对如何将这两个表与静态数据集成到查询中感到磕磕绊绊。只要“结果”表中至少有一行对应于挂起表中的每一行,以下查询就可以正常工作(但是,对于仅存在于“待处理”但尚未存在的行,它不会返回任何内容'结果'):

SELECT 
 pending.cl,
 pending.id,
 pending.buildid,
 pending.build_type,
 pending.active,
 pending.submittracker,
 pending.os,pending.arch,
 pending.osversion,
 pending.branch,
 pending.comment,
 osversmap.osname,
 buildlist.buildname,
 results.logurl 
FROM pending ,osversmap ,buildlist ,results 
WHERE 
 pending.buildid=buildlist.id 
 AND pending.os=osversmap.os 
 AND pending.osversion=osversmap.osversion 
 AND pending.owner='$owner' 
 AND pending.completed='f' 
 AND results.hostname=pending.active 
 AND results.submittracker=pending.submittracker 
 AND pending.cl=results.cl 
 AND results.current_status!='PASSED' 
 AND results.current_status NOT LIKE '%FAILED' 
ORDER BY pending.submittracker,pending.branch,pending.os,pending.arch

提前感谢!

2 个答案:

答案 0 :(得分:0)

以下是否适用于您?

SELECT  pending.cl,
        pending.id,
        pending.buildid,
        pending.build_type,
        pending.active,
        pending.submittracker,
        pending.os,
        pending.arch,
        pending.osversion,
        pending.branch,
        pending.comment,
        osversmap.osname,
        buildlist.buildname,
        results.logurl
FROM pending
    JOIN osversmap
        ON ( pending.os = osversmap.os
            AND pending.osversion = osversmap.osversion )
    JOIN buildlist
        ON ( pending.buildid = buildlist.id )
    LEFT OUTER JOIN results
        ON ( pending.active = results.hostname
            AND pending.submittracker = results.submittracker
            AND pending.cl = results.cl 
            AND results.current_status != 'PASSED'
            AND results.current_status NOT LIKE '%FAILED'
            )
WHERE pending.owner = '$owner'
    AND pending.completed = 'f'
ORDER BY pending.submittracker,
    pending.branch,
    pending.os,
    pending.arch

答案 1 :(得分:0)

  

所有这一切都与这个问题非常相似,只不过我增加了两个附加表和静态数据(buildlist& osversmap)的负担:

最简单的方法是构建一个返回正确行而不引用buildlist和osversmap的视图。然后将这两个表连接到视图。

CREATE VIEW your-meaningful-view-name AS
SELECT 
 pending.cl,
 pending.id,
 pending.buildid,
 pending.build_type,
 pending.active,
 pending.submittracker,
 pending.os,pending.arch,
 pending.osversion,
 pending.branch,
 pending.comment,
 results.logurl 
FROM pending
-- No DDL or sample INSERT statements. You might need an outer join.
INNER JOIN results 
        ON (results.hostname=pending.active AND
            results.submittracker=pending.submittracker AND
            results.cl=pending.cl)
WHERE pending.owner='$owner' AND
      pending.completed='f' AND
      -- Are *both* these really necessary?
      results.current_status!='PASSED' AND
      results.current_status NOT LIKE '%FAILED' 

然后

SELECT  osversmap.osname, buildlist.buildname, ymvn.*,
FROM your-meaningful-view-name ymvn
INNER JOIN osversmap ON ymvn.os=osversmap.os  
                    AND ymvn.osversion=osversmap.osversion 
INNER JOIN buildlist ON ymvn.buildid=buildlist.id 
ORDER BY ymvn.submittracker, ymvn.branch, ymvn.os, ymvn.arch