我需要将一个Header Table和六个Detail Tables组合成一个结果。为了演示我创建了一个非常简单的示例如下:
DECLARE @MyHeader TABLE (HeaderPK int, Name varchar(100), Total smallmoney) INSERT INTO @MyHeader (HeaderPK, Name, Total) SELECT 1, 'ABC Company', 1600 DECLARE @MyDetail1 TABLE (Detail1PK int, HeaderFK int, Detail1Description varchar(100), Detail1Amount smallmoney) INSERT INTO @MyDetail1 (Detail1PK, HeaderFK, Detail1Description, Detail1Amount) SELECT 1, 1, 'Detail 1A', 100 UNION SELECT 2, 1, 'Detail 1B', 300 DECLARE @MyDetail2 TABLE (Detail2PK int, HeaderFK int, Detail2Description varchar(100), Detail2AmountA smallmoney, Detail2AmountB smallmoney) INSERT INTO @MyDetail2 (Detail2PK, HeaderFK, Detail2Description, Detail2AmountA, Detail2AmountB) SELECT 1, 1, 'Detail 2A', 100, 100 UNION SELECT 2, 1, 'Detail 2B', 200, 200 UNION SELECT 3, 1, 'Detail 3C', 300, 300 -- Returns 2 Rows, Expected 2 SELECT MyHeader.* ,MyDetail1.* FROM @MyHeader MyHeader FULL JOIN @MyDetail1 MyDetail1 ON MyHeader.HeaderPK = MyDetail1.HeaderFK ORDER BY MyDetail1.Detail1PK -- Returns 6 Rows, Expected 3 SELECT MyHeader.* ,MyDetail1.* ,MyDetail2.* FROM @MyHeader MyHeader FULL JOIN @MyDetail1 MyDetail1 ON MyHeader.HeaderPK = MyDetail1.HeaderFK FULL JOIN @MyDetail2 MyDetail2 ON MyHeader.HeaderPK = MyDetail2.HeaderFK
注意:
在示例中,详细信息表具有类似的结构。在生产系统中,它们非常不同。
答案 0 :(得分:2)
根据详细信息表的插槽向上检索,这将为您提供所需的内容。坦率地说,我只是因为它有点有趣而展示这段代码。通常没有充分理由进行此类查询。
为了提高传输效率,最好不要重复标题列中的数据:
Header
Detail1
Detail2
Detail3
etc
SQL查询
DECLARE @MyHeader TABLE (HeaderPK int, Name varchar(100), Total smallmoney)
INSERT INTO @MyHeader (HeaderPK, Name, Total)
SELECT 1, 'ABC Company', 1600
DECLARE @MyDetail1 TABLE (Detail1PK int, HeaderFK int, Detail1Description varchar(100), Detail1Amount smallmoney)
INSERT INTO @MyDetail1 (Detail1PK, HeaderFK, Detail1Description, Detail1Amount)
SELECT 1, 1, 'Detail 1A', 100
UNION SELECT 2, 1, 'Detail 1B', 300
DECLARE @MyDetail2 TABLE (Detail2PK int, HeaderFK int, Detail2Description varchar(100), Detail2AmountA smallmoney, Detail2AmountB smallmoney)
INSERT INTO @MyDetail2 (Detail2PK, HeaderFK, Detail2Description, Detail2AmountA, Detail2AmountB)
SELECT 1, 1, 'Detail 2A', 100, 100
UNION SELECT 2, 1, 'Detail 2B', 200, 200
UNION SELECT 3, 1, 'Detail 3C', 300, 300
DECLARE @MyDetail3 TABLE (Detail3PK int, HeaderFK int, Detail3Description sysname)
INSERT INTO @MyDetail3 (Detail3PK, HeaderFK, Detail3Description)
SELECT 1, 1, 'Detail 3A'
UNION SELECT 2, 1, 'Detail 3B'
-- Returns 6 Rows, Expected 3
SELECT
MyHeader.*
,MyDetail1.*
,MyDetail2.*
,MyDetail3.*
FROM
@MyHeader MyHeader
LEFT JOIN
(SELECT *, RN=ROW_NUMBER() over (order by Detail1PK) FROM @MyDetail1) MyDetail1
FULL JOIN
(SELECT *, RN=ROW_NUMBER() over (order by Detail2PK) FROM @MyDetail2) MyDetail2
ON MyDetail1.HeaderFK = MyDetail2.HeaderFK AND MyDetail1.RN = MyDetail2.RN
FULL JOIN
(SELECT *, RN=ROW_NUMBER() over (order by Detail3PK) FROM @MyDetail3) MyDetail3
ON COALESCE(MyDetail1.HeaderFK, MyDetail2.HeaderFK) = MyDetail3.HeaderFK
AND COALESCE(MyDetail1.RN, MyDetail2.RN) = MyDetail3.RN
ON MyHeader.HeaderPK = COALESCE(MyDetail1.HeaderFK, MyDetail2.HeaderFK)
您可以通过向COALSECE添加更多详细信息来扩展到更多详细信息表,因此第6个详细信息表将是
FULL JOIN
(SELECT *, RN=ROW_NUMBER() over (order by Detail6PK) FROM @MyDetail6) MyDetail6
ON COALESCE(MyDetail1.HeaderFK, MyDetail2.HeaderFK, MyDetail3.HeaderFK,
MyDetail4.HeaderFK, MyDetail5.HeaderFK) = MyDetail6.HeaderFK
AND COALESCE(MyDetail1.RN, MyDetail2.RN, MyDetail3.RN, MyDetail4.RN, MyDetail5.RN) = MyDetail6.RN
答案 1 :(得分:0)
对每一行执行每个连接。因此,如果您在一个匹配2行的表上连接一行表,那么您将获得2行。如果你在一个包含3行的表上加入它,你会获得6行,依此类推。
一种解决方案是执行多个SQL语句,每个详细信息表一个。客户端可以使用等效的SqlDataReader.NextResult()
移动到下一个结果。
另一种选择是将union all
不同的陈述放在一起;这将导致列太多,但行数将减少。
答案 2 :(得分:0)
当你将@ MyDetail1与@MyHeader匹配时,你会得到两行。如果你将@ MyDetail2与@MyHeader匹配,你会获得三行。但是,在上一次连接中,您不告诉系统如何将@ MyDetail1中的两行与@ MyDetail2中的三行匹配,因此系统假定您要将@ MyDetail1的每一行与@ MyDetail2的每一行匹配得到2 x 3行或6行。
解决方案: