【问题标题】:How to join master table to multiple details table with extra rows of details cell filled with NULL如何将主表连接到多个详细信息表,其中额外的详细信息单元格填充为 NULL
【发布时间】:2015-02-14 12:38:37
【问题描述】:

我不确定问题标题是否合适。我的问题类似于线程 How to Join Multiple Detail Tables to Header Table 。但这也给出了重复的记录。 这是我的情况
我有一个主表和两个详细表。

MasterID | Name  
-----------------------    // Master table
1          Item1
2          Item2
3          Item3
4          Item4
5          Item5

-----------------------

Det1ID | FKMasterID | Value 
-----------------------------
1         1           Det1-Val1
2         1           Det1-Val2
3         2           Det1-Val3


Det2ID | FKMasterID | Value
-----------------------------
1         1            Det2-Val1
2         1            Det2-Val2
3         1            Det2-Val3
4         3            Det2-Val4
5         5            Det2-Val5
----------------------------------

表格有点像这样。
当我进行所需的左右连接时,我会以这种方式得到结果。

MasterID | Name   | Det1ID | Det1Value | Det2ID | Det2Value
------------------------------------------------------------
1          Item1    1       Det1-Val1    1       Det2-Val1 
1          Item1    1       Det1-Val1    2       Det2-Val2
1          Item1    1       Det1-Val1    3      Det2-Val3
1          Item1    2       Det1-Val2    1       Det2-Val1
1          Item1    2       Det1-Val2    2       Det2-Val2
1          Item1    2       Det1-Val2    3       Det2-Val3
2          Item2    3       Det1-Val3    NULL    NULL
3          Item3    NULL    NULL         4       Det2-Val4
4          Item4    NULL    NULL         NULL    NULL
5          Item5    NULL    NULL         5       Det2-Val5
-------------------------------------------------------------

我期望得到的是

MasterID | Name   | Det1ID | Det1Value | Det2ID | Det2Value
------------------------------------------------------------
1          Item1    1       Det1-Val1    1       Det2-Val1 
1          Item1    2       Det1-Val2    2       Det2-Val2
1          Item1    NULL    NULL         3       Det2-Val3
2          Item2    3       Det1-Val3    NULL    NULL
3          Item3    NULL    NULL         4       Det2-Val4
4          Item4    NULL    NULL         NULL    NULL
5          Item5    NULL    NULL         5       Det2-Val5
------------------------------------------------------------

我不希望任何主项目的详细信息值重复。

有没有办法做到这一点?只有用游标迭代才是方法?? 一点帮助表示赞赏。

谢谢,

【问题讨论】:

  • 您的 Det1Id 和 Det2Id 值在您的实际或预期输出中都没有意义。请显示您的查询、准确的输入、准确的输出和所需的准确输出。
  • 如果您的问题与其他问题相似,请说明该问题的哪一部分不适用于您的情况。
  • 因此,如果详细信息 1 中有 3 个 MasterID=1 行,详细信息 2 有 100 行,那么您将输出 100 MasterID=1 行,其中 Det2Values 是从详细信息 2 以相同顺序向下的 100,并且Det1Values 是细节 1 中的 3,以相同的顺序向下,后跟 97 个空值?
  • 正是@philipxy! D1 中有 100 个细节和 97 个空值 + 3 个细节 n D2。 mwillemse 解决方案实现了它,但正如我在该答案的评论中提到的一个问题。
  • 请在您的问题中描述您想要的内容以及正确的数据。评论是短暂的。

标签: sql-server join multiple-tables


【解决方案1】:

事实证明它比我最初想象的要复杂一些,但下面的方法应该可以解决问题。代码应该很容易解释。

WITH [master] AS(
    SELECT * FROM (VALUES
         (1, 'Item1')
        ,(2, 'Item2')
        ,(3, 'Item3')
        ,(4, 'Item4')
        ,(5, 'Item5')
    ) AS T(ID, Value)
),
Det1 AS (
    SELECT * FROM (VALUES
         (1, 1, 'Det1-Val1')
        ,(2, 1, 'Det1-Val2')
        ,(3, 2, 'Det1-Val3')
    ) AS T(ID, MasterID, Value)
),
Det2 AS (
    SELECT * FROM (VALUES
         (1, 1, 'Det2-Val1')
        ,(2, 1, 'Det2-Val2')
        ,(3, 1, 'Det2-Val3')
        ,(4, 3, 'Det2-Val4')
        ,(5, 5, 'Det2-Val5')
    ) AS T(ID, MasterID, Value)
),
Det1Numbered AS(
    SELECT MasterID     = M.ID ,
           MasterValue  = M.Value ,
           Det1ID       = D.ID ,
           Det1Value    = D.Value, 
           RowNr        = ROW_NUMBER() OVER (PARTITION BY M.ID ORDER BY D.ID)
    FROM  [master] AS M
        LEFT JOIN Det1 AS D
            ON M.ID = D.MasterID
),
Det2Numbered AS(
    SELECT MasterID     = M.ID ,
           MasterValue  = M.Value ,
           Det2ID       = D.ID ,
           Det2Value    = D.Value, 
           RowNr        = ROW_NUMBER() OVER (PARTITION BY M.ID ORDER BY D.ID)
    FROM  [master] AS M
        LEFT JOIN Det2 AS D
            ON M.ID = D.MasterID
)
SELECT MasterID         = COALESCE(D1.MasterID, D2.MasterID),
       MasterValue      = COALESCE(D1.MasterValue, D2.MasterValue),
       D1.Det1ID ,
       D1.Det1Value ,
       D2.Det2ID ,
       D2.Det2Value
FROM Det1Numbered AS D1
    FULL JOIN Det2Numbered AS D2
        ON D1.MasterID = D2.MasterID
        AND D2.RowNr = D1.RowNr
ORDER BY MasterID

编辑:确实有一个小错误,我已经更新了上面的查询。修复方法是将PARTITION BY D.MasterID 替换为PARTITION BY M.ID,现在RowNr 从1 开始,用于之前版本中没有的每个主记录。

【讨论】:

  • 嗨@MWillemse,你的把戏几乎做到了。但是当详细信息“D1Numbered”和“D2Numbered”中存在不平衡的 NULL 条目时,它仍然存在问题。不平衡这个词的意思是,如果一个主项目在“D1”中没有详细信息,那么应该有另一个项目(或同一项目)在“D2”中没有详细信息条目。我试图以某种方式摆脱这个问题。但如果您有更好的解决方案,请告诉我
  • @a4ashiq 你不清楚!在您的问题中使用更多单词和(正确)示例来解释您的意思。仔细参考事物的特定部分。您给我们提供了不正确的示例和不清楚的描述。我们无法读懂你的想法。还请在您的问题中就您所报告的内容解释采用这种格式的要点。 (一个SQLFiddle。)
  • @philipxy ,我已经用新场景更正了我的示例。我在结果表中给出了错误的 DetID。我也纠正了这一点。让别人不糊涂。我通过修改 MWillemse 的答案解决了我的问题。
  • @MWillemse ,我已经通过对您的查询进行轻微修改来解决它。我从“Det1”和“Det2”中删除了“主”表的 JOIN,并将该 JOIN 与结果表放在最后。那是我的工作。谢谢你
【解决方案2】:

我不太确定,但我认为您想要的是:

SELECT m.MasterID, m.Name, d1.DetailsID Det1ID, d1.Value Det1Value, d2.DetailsID Det2ID, d2.Value Det2Value
FROM Details1 d1
    FULL OUTER JOIN Details2 d2 ON d1.FKMasterID = d2.FKMasterID AND d1.Value = d2.Value
    RIGHT JOIN Master m ON d1.FKMasterID = m.MasterID OR d2.FKMasterID = m.MasterID

如果值匹配,这将只显示两个详细信息表,这似乎是您想要的?

【讨论】:

  • 这仍然有 DetNValue 值出现在多个输出行中,但示例没有。
  • @ChrisV,这是一个关闭,但仍包含多行。它为某些项目的每个 Det1 和 Det2 创建单独的行。我的 DetID 并非针对所有项目都继续。可能就是这个问题。所有其他记录(带有连续 ID)都很完美。
猜你喜欢
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
  • 2010-12-06
  • 2015-11-01
相关资源
最近更新 更多