1

我有一些如下所示的代码:

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

基本上,我想通过 invoices 表中的标识符来查找 shipping 表和 details 表。但是,我还想使用以下内容加入这两个表:

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)

有没有办法将这两者干净地结合在一起?

4

5 回答 5

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
)
于 2013-10-03T15:46:20.750 回答
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
于 2013-10-03T16:03:20.510 回答
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
  • 第二个分支仅返回值 if invoices.detail_id IS NOT NULL

瞧。

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

于 2013-10-04T01:34:33.283 回答
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
      )
于 2013-10-03T15:58:37.560 回答
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)
)

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

于 2013-10-03T18:09:09.623 回答