在SQL中连接多个表,同时限制指数结果

时间:2012-10-03 08:47:56

标签: sql oracle oracle8i

我已经搜索了Google和Stack Overflow以获得我的查询答案,但我觉得我缺乏SQL词汇是我找到答案的方式,因为我认为这是一个常见的问题。我总是欢迎任何有助于我需要阅读的方向的点。

关于这个问题,我正在尝试加入Oracle 8i中的三个表,例如,公司表,发票表和作业表,发票表和作业表之间没有链接。我希望在一个查询中我可以链接所有三个表,返回公司的所有发票和所有工作,而不返回每个发票的所有工作(请参阅下面的示例结果)。

我想看看:

Company 1   Invoice 1   Job 1
Company 1   Invoice 2   Job 2
Company 1   Invoice 3   Job 3

我不想看到:

Company 1   Invoice 1   Job 1
Company 1   Invoice 1   Job 2
Company 1   Invoice 1   Job 3
Company 1   Invoice 2   Job 1
Company 1   Invoice 2   Job 2
Company 1   Invoice 2   Job 3
Company 1   Invoice 3   Job 1
Company 1   Invoice 3   Job 2
Company 1   Invoice 3   Job 3

一如既往地感谢您提供的任何帮助。

编辑:

基本上,Invoice和Job Tables都有一个Company Table Key字段,只是Job和Invoice表没有直接相互链接。如果实例出现时有2个发票和3个工作,我最好还是要显示它,反之亦然:

Company 1   Invoice 1   Job 1
Company 1   Invoice 2   Job 2
Company 1               Job 3

虽然看到这样的问题让我觉得这比我希望的更容易回答。

1 个答案:

答案 0 :(得分:1)

您的要求意味着您的架构存在问题。我在这种情况下的第一个建议是修改您的架构:将job_id添加到invoiceinvoice_id添加到job(或NN关系表invoice_job )。

如果您不愿意更新架构,则可以使用将进行连接的查询。 following query基本上会一对一地加入jobinvoice

SELECT c.company_id, ij.job_id, ij.invoice_id
  FROM company c
  LEFT JOIN (SELECT job_id, invoice_id, 
                    NVL(j.company_id, i.company_id) company_id
               FROM (SELECT j.job_id, j.company_id,
                            row_number() OVER (PARTITION BY company_id
                                           ORDER BY job_id) job_no
                       FROM job j) j
               FULL OUTER JOIN 
                    (SELECT i.invoice_id, i.company_id,
                            row_number() OVER (PARTITION BY company_id
                                           ORDER BY invoice_id) invoice_no
                       FROM invoice i) i
                    ON j.company_id = i.company_id
                   AND j.job_no = i.invoice_no) ij
              ON c.company_id = ij.company_id

这里的连接条件是人为的。如果您删除发票,则作业和发票关系可能会更改。

如果这两个表确实无关,您可能希望以不同的方式显示结果,for example

SQL> SELECT cj.company_id, cj.jobs,
  2         listagg(i.invoice_id, ',')
  3            WITHIN GROUP (ORDER BY i.invoice_id) invoices
  4    FROM (SELECT c.company_id,
  5                 listagg(j.job_id, ',') WITHIN GROUP (ORDER BY job_id) jobs
  6            FROM company c LEFT JOIN job j ON c.company_id = j.company_id
  7           GROUP BY c.company_id) cj
  8    LEFT JOIN invoice i ON cj.company_id = i.company_id
  9  GROUP BY cj.company_id, cj.jobs;

COMPANY_ID  JOBS   INVOICES
----------- ------ --------
1           1,2,3  1,2