我有一些代码如下:
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)
有没有办法将这两者完美地结合在一起?
答案 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À。
我有一种刺痛的感觉,你的数据库架构留下了改进的空间。 :)