首页 > 解决方案 > 从 SQL Server 以非表格形式返回数据

问题描述

请原谅我的模糊标题,但我找不到更合适的词来总结我的问题。

在数据库中有两个表,我想组合并从中检索数据:

Id   Name     Description               Id       Batch    Quantity
1    Item_A     ....                     1         1A       25
2    Item_B     ....                     1         1B       25
3    Item_C     ....                     1         1C       50
.                                        1         1D       50
.                                        2         2A       21
                                         .          .        .
                                         .          .        .

我想将第二个表中的数据与其在第一个表中的相应 ID 结合起来,即为批次项目提供适当的名称和描述。

一个简单的连接确实为我提供了我想要的数据,但连接这两个表会产生一个大表,其中每个具有相同 ID 的批次都重复描述列,即使相同 ID 的只有一个描述数据就足够了。

有没有什么方法可以将 Name 和 Description 数据结合到第二个表中的相应 Id 值,但不会产生冗余数据,其中 Name 和相当长的 Description 列不会为同一个 Id 重复?

我尝试过的一种解决方案是分别检索两个表,但通过按照 Id 以相同的顺序进行排序。通过这种方式,我可以使用简单的映射函数来创建一个伪对象,如下所示:

Main{
   List<Item> Items
}
Item{
   string Name
   string Description
   List<Quantity> Quantities
}
Quantity{
    string Batch
    int Quantity
}

然而,这破坏了两种语言的数据操作步骤,并使代码变得复杂且难以理解。

最好,我想一次检索所有项目的数据(执行一次存储过程)。有人能证明这是一个好方法吗?

标签: sql-serverdatabasetsqljoin

解决方案


您可以尝试使用 XML。

以下是如何在 MS SQL Server 中生成父/子一对多 XML。

SQL

-- DDL and sample data population, start
DECLARE @parent TABLE (ID INT PRIMARY KEY, ItemName VARCHAR(30));
INSERT INTO @parent (ID, ItemName) VALUES
(1, 'Item_A'),
(2, 'Item_B');

DECLARE @child TABLE (ID INT IDENTITY PRIMARY KEY, ParentID INT, Batch CHAR(2), Quantity INT);
INSERT INTO @child (ParentID,  Batch,  Quantity) VALUES
(1, '1A', 25),
(1, '1B', 25),
(1, '1C', 50),
(2, '1D', 50),
(2, '2A', 21);
-- DDL and sample data population, end

SELECT p.*
    , (
    SELECT c.* 
    FROM @child AS c
    WHERE c.ParentID = p.ID
    FOR XML PATH('r'), TYPE, ROOT('child')
)    
FROM @parent AS p
FOR XML PATH('r'), TYPE, ROOT('root');

输出

<root>
  <r>
    <ID>1</ID>
    <ItemName>Item_A</ItemName>
    <child>
      <r>
        <ID>1</ID>
        <ParentID>1</ParentID>
        <Batch>1A</Batch>
        <Quantity>25</Quantity>
      </r>
      <r>
        <ID>2</ID>
        <ParentID>1</ParentID>
        <Batch>1B</Batch>
        <Quantity>25</Quantity>
      </r>
      <r>
        <ID>3</ID>
        <ParentID>1</ParentID>
        <Batch>1C</Batch>
        <Quantity>50</Quantity>
      </r>
    </child>
  </r>
  <r>
    <ID>2</ID>
    <ItemName>Item_B</ItemName>
    <child>
      <r>
        <ID>4</ID>
        <ParentID>2</ParentID>
        <Batch>1D</Batch>
        <Quantity>50</Quantity>
      </r>
      <r>
        <ID>5</ID>
        <ParentID>2</ParentID>
        <Batch>2A</Batch>
        <Quantity>21</Quantity>
      </r>
    </child>
  </r>
</root>

推荐阅读