如何从第4个表中通过id合并三个表?

时间:2013-10-02 18:03:26

标签: sql sql-server tsql

我们有一个'主'表和另外三个表,下面有一些细节。

                +----------+
                |  TAB_A   |
                +----------+
               *|PK ID_A   |
 +----------+ / |FK ID_MAIN|
 |TableMain |/  | DATA_A   |
 ------------   ============
 |PK ID_MAIN|   +----------+   
 | Main_data|--*|  TAB_B   |
 |          |   +----------+
 ============   |PK ID_B   |
            |   |FK ID_MAIN|
            |   | DATA_B   |
            *   ============
       +-----------+
       | TAB_C     |
       +-----------+
       | PK ID_C   |
       | FK ID_MAIN| 
       | DATA_C    |
       =============

示例值:

        TableMain:            
    ID_MAIN   Main_data
       1        main1
       2        main2
       3        main3

       TAB_A           |          TAB_B          |           TAB_C
ID_A  ID_MAIN  DATA_A  | ID_B  ID_MAIN  DATA_B   |   ID_C  ID_MAIN  DATA_C
 1      2        A2    |  1      1       B3      |    1       3       C3
 2      1        A1    |  2      1       B3_1    |
 3      1        A1_1
 4      3        A3
 5      1        A1_2

我想要来自TableMain的每个rekord的TAB_A,TAB_B和TAB_C的所有细节。 输出应该看起来像那样

ID_MAIN  | Main_data | DATA_A | DATA_B | DATA_C |
-------------------------------------------------
1        |   main1   |        |  B3    |        |
         |   main1   |        |  B3_1  |        |
2        |   main2   |  A2    |        |        |
3        |   main3   |  A3    |        |   C3   |

4 个答案:

答案 0 :(得分:1)

由于您希望将来自不同表的值放在同一行上,因此您需要以某种方式将它们相互关联。在没有实际关系的情况下,你可能不得不做一个。一个建议是在三个从属表中为每个ID_MAIN分配行号,并使用这些数字进行匹配。

如果您使用的是SQL Server 2005或更高版本,则可以使用ROW_NUMBER分析函数添加行号,整个查询可能如下所示:

WITH A_ranked AS (
  SELECT *, ROW_NUM = ROW_NUMBER() OVER (PARTITION BY ID_MAIN ORDER BY ID_A)
  FROM TAB_A
),
B_ranked AS (
  SELECT *, ROW_NUM = ROW_NUMBER() OVER (PARTITION BY ID_MAIN ORDER BY ID_B)
  FROM TAB_B
),
C_ranked AS (
  SELECT *, ROW_NUM = ROW_NUMBER() OVER (PARTITION BY ID_MAIN ORDER BY ID_C)
  FROM TAB_C
)
SELECT
  ID_MAIN = COALESCE(a.ID_MAIN, b.ID_MAIN, c.ID_MAIN),
  m.Main_data,
  ROW_NUM = COALESCE(a.ROW_NUM, b.ROW_NUM, c.ROW_NUM),
  a.DATA_A,
  b.DATA_B,
  c.DATA_C
FROM
  A_ranked AS a
FULL JOIN
  B_ranked AS b ON b.ID_MAIN = a.ID_MAIN
               AND b.ROW_NUM = a.ROW_NUM
FULL JOIN
  C_ranked AS c ON c.ID_MAIN = COALESCE(a.ID_MAIN, b.ID_MAIN)
               AND c.ROW_NUM = COALESCE(a.ROW_NUM, b.ROW_NUM)
RIGHT JOIN
  TableMain AS m ON m.ID_MAIN = COALESCE(a.ID_MAIN, b.ID_MAIN, c.ID_MAIN)
;

您可以查看此查询的实时演示at SQL Fiddle

答案 1 :(得分:0)

看起来你想要的只是一个简单的LEFT JOIN

select TableMain.ID_MAIN, TableMain.Main_data, TAB_A.DATA_A, TAB_B.DATA_B, TAB_C.DATA_C
from TableMain
left join TAB_A on TAB_A.ID_MAIN=TableMain.ID_MAIN
left join TAB_B on TAB_B.ID_MAIN=TableMain.ID_MAIN
left join TAB_C on TAB_C.ID_MAIN=TableMain.ID_MAIN;

文档here

答案 2 :(得分:0)

嗨,请尝试这个希望,这有助于你感谢

SELECT    dbo.TableMail.ID_MAIN, dbo.TableMail.Main_Data, 
          CASE WHEN DATA_A IS NULL  THEN '' ELSE DATA_A END AS DATA_A, 
          CASE WHEN DATA_B IS NULL  THEN '' ELSE DATA_B END AS DATA_B, 
          CASE WHEN DATA_C IS NULL THEN ''     ELSE  DATA_C END AS DATA_C

FROM      dbo.TableMail LEFT OUTER JOIN
          dbo.Table_C ON dbo.TableMain.ID_MAIN = dbo.Table_C.ID_MAIN LEFT OUTER   JOIN
          dbo.Table_A ON dbo.TableMain.ID_MAIN = dbo.Table_A.ID_MAIN LEFT OUTER  JOIN
          dbo.Table_B ON dbo.TableMain.ID_MAIN = dbo.Table_B.ID_MAIN

GROUP BY  dbo.TableMain.ID_MAIN, dbo.TableMain.Main_Data, CASE WHEN DATA_A IS NULL THEN '' ELSE DATA_A END, CASE WHEN DATA_B IS NULL 
           THEN '' ELSE DATA_B END, CASE WHEN DATA_C IS NULL THEN '' ELSE DATA_C  END

答案 3 :(得分:0)

这不仅仅是左连接的简单三重奏吗? Fiddle here

SELECT
            M.[ID_MAIN],
            M.[Main_data],
            A.[DATA_A],
            B.[DATA_B],
            C.[DATA_C]
    FROM
            [TableMain] M
        LEFT JOIN
            [TAB_A] A
                ON A.[ID_MAIN] = M.[ID_MAIN]
        LEFT JOIN
            [TAB_B] B
                ON B.[ID_MAIN] = M.[ID_MAIN]
        LEFT JOIN
            [TAB_C] C
                ON C.[ID_MAIN] = M.[ID_MAIN]
    ORDER BY
            M.[ID_MAIN] ASC