我们有一个系统可以跟踪 MS SQL 数据库中的包。每包包含 1-3 盒。所有包裹都至少有一个盒子,“BoxSide”。此外,它们旁边还可能有一个“BoxOuter”,并且该盒子内部可能有“BoxInner”。每个盒子里都有我们保存数据的内容。
因此,总共有五个单独的表:一张包含包装信息,一张代表每个盒子(侧面、外部和内部),还有一张包含每个盒子内容的数据。它们之间的关系如下图所示:
我想要做的是运行一个查询,将所有数据放在一个报告中,每个包有一条记录,每个框的内容有一个字段,将不适用的字段留空。比如:
Package.*、BoxSide.Data1、Boxside.Data2、BoxOuter.Data1、BoxOuter.Data2、BoxInner.Data1、BoxInner.Data2
重申:
我尝试了各种连接来将这些数据链接回一起,但我似乎总是以丢失包裹(如果它们没有特定的盒子类型)或不同盒子类型的同一包裹多次重复记录而告终。这里列出了太多失败的尝试。
有懂 SQL 的人可以帮我做一个可以做到这一点的查询吗?
您需要使用
LEFT JOIN
来获取Package
中的每条记录,无论它在其他表中是否有对应的值:
SELECT P.ID, p.Time, P.Type, P.Name, P.location,
s.ID, sc.ID, sc.Data1, sc.Data2,sc.Data3
o.ID, oc.ID, oc.Data1, oc.Data2, oc.Data3
i.ID, ic.ID, ic.Data1, ic.Data2, ic.Data3
FROM Package p
LEFT JOIN BoxSide s ON p.ID = s.PackageID
LEFT JOIN Contents sc ON s.ID = sc.ParentID
LEFT JOIN BoxOuter o ON p.ID = o.PackageID
LEFT JOIN Contents oc ON o.ID = oc.ParentID
LEFT JOIN BoxInner i ON o.ID = i.BoxOuterID
LEFT JOIN Contents ic ON i.ID = ic.ParentID
请注意,您还必须多次
LEFT JOIN
Contents
表,每次使用不同的别名将其链接到每个父表。
您是否尝试过在 BoxOuter 和 BoxInner 上应用左连接?无论右侧是否有匹配项,这都应该返回您的软件包。
SELECT Package.*,
bsc.Data1,
bsc.Data2,
boc.Data1,
boc.Data2,
bic.Data1,
bic.Data2
FROM Package p
INNER JOIN BoxSide bs ON p.id = bs.packageid
LEFT JOIN BoxOuter bo ON p.id = bo.packageid
LEFT JOIN BoxInner bi ON bo.id = bi.boxouterid
INNER JOIN Contents bsc ON bs.id = bsc.parentid
INNER JOIN Contents boc ON bo.id = boc.parentid
INNER JOIN Contents bic ON bi.id = bic.parentid