我可以在连接中引用后面的表吗?

时间:2013-10-03 15:17:49

标签: sql postgresql join

我有一些代码如下:

SELECT *
FROM invoices
LEFT JOIN shipments ON (
    shipments.id = invoices.shipment_id
)
LEFT JOIN details ON (
    details.id = invoices.detail_id
)

基本上,我想通过发票表中的标识符查找货件表和详细信息表。但是,我还想使用以下内容加入这两个表:

SELECT *
FROM shipments
JOIN details ON (shipments.order = details.order)

基本上,如果找到(invoices.shipment_id,invoices.detail_id)中的任何一个,我想要一种拉两个表的方法。但是,我无法在连接中引用后面的表,因此我不能只执行以下操作:

SELECT *
FROM invoices
LEFT JOIN shipments ON (
    shipments.id = invoices.shipment_id
    OR shipments.order = details.order
)
LEFT JOIN details ON (
    details.id = invoices.detail_id
)

拉两张桌子时有没有办法做到这一点?

为清晰起见编辑:

这是一个示例表结构

CREATE TABLE invoices (
    id integer PRIMARY KEY,
    shipment_id integer,
    detail_id integer,
    data text
)

CREATE TABLE shipments (
    id integer PRIMARY KEY,
    data text
)

CREATE TABLE details (
    id integer PRIMARY KEY,
    shipment_id REFERENCES shipments (id),
    data text
)

invoices.shipment_id可能包含也可能不包含shipments.id,而invoices.detail_id可能包含也可能不包含details.id

如果invoices.shipment_id包含有效ID,我需要执行以下操作:

SELECT
    shipments.data as shipment_data,
    details.data as detail_data,
FROM invoices
JOIN shipments ON (invoices.shipment_id = shipments.id)
JOIN details ON (details.shipment_id = shipments.id)

如果invoices.detail_id包含有效ID,我需要执行以下操作:

SELECT
    shipments.data as shipment_data,
    details.data as detail_data,
FROM invoices
JOIN details ON (invoices.detail_id = details.id)
JOIN shipments ON (details.shipment_id = shipments.id)

有没有办法将这两者完美地结合在一起?

5 个答案:

答案 0 :(得分:1)

尝试

select * from invoices
left join (
  select shipments.id as ids, details.id as idd, * from shipments
  outer join details on (
   shipments.order=details.order
  )
) as sd on (
 sd.ids=invoices.shipment_id OR
 sd.idd = invoices.detail_id
)

答案 1 :(得分:1)

抱歉,我认为问题是关于SQL服务器所以请原谅我,如果我的语法错误。但我很确定该查询将在postgres中有效。

这看起来很奇怪..但如果我理解正确,那么下面将完成这项工作

SELECT *
FROM shipments INNER JOIN
details ON shipments.order = details.order RIGHT JOIN
invoices ON details.id = invoices.detail_id 
AND shipments.id = invoices.shipment_id

答案 2 :(得分:0)

目前尚不清楚你想要什么。也许这个:

SELECT *
FROM invoices
  LEFT JOIN shipments ON
    shipments.id = invoices.shipment_id
  LEFT JOIN details ON
    details.id = invoices.detail_id
WHERE ( shipments.order = details.order
     OR shipments.order IS NULL
     OR details.order IS NULL
      )

答案 3 :(得分:0)

我能想到的最好的解决方案是:

SELECT DISTINCT * FROM
(
    SELECT
        shipments.data as shipment_data,
        details.data as detail_data,
    FROM invoices
    JOIN shipments ON (invoices.shipment_id = shipments.id)
    JOIN details ON (details.shipment_id = shipments.id)

    UNION

    SELECT
        shipments.data as shipment_data,
        details.data as detail_data,
    FROM invoices
    JOIN details ON (invoices.detail_id = details.id)
    JOIN shipments ON (details.shipment_id = shipments.id)
)

这不是最漂亮的解决方案,但它正确地使用了所有三个表上的索引,并在需要时返回两组记录。

答案 4 :(得分:0)

使用UNION ALL

假设只有(invoices.shipment_id, invoices.detail_id)中的一个可以包含值而另一个必须为NULL并且您实际上是使用CHECK约束强制执行此规则 - 因为其他任何内容会导致歧义。

SELECT s.data AS shipment_data, d.data AS detail_data
FROM   invoices  i
JOIN   shipments s ON s.id = i.shipment_id
JOIN   details   d ON d.shipment_id = s.id

UNION ALL
SELECT s.data, d.data
FROM   invoices  i
JOIN   details   d ON d.id = i.detail_id
JOIN   shipments s ON s.id = d.shipment_id
  • 第一个分支仅返回值invoices.shipment_id IS NOT NULL
  • 第二个分支仅返回invoices.detail_id IS NOT NULL
  • 时的值

VOILÀ。

我有一种刺痛的感觉,你的数据库架构留下了改进的空间。 :)