SQL Query使用单个不同的字段获取多个记录

时间:2018-02-13 09:28:56

标签: sql sql-server relational-database

我有一个表(它不是真实的表,而是另一个查询的结果),如下所示:

ID | NAME | OPTIONAL_ID | OPTIONAL_NAME | OTHER FIELDS
1  | abc  | 34          | optional 1    | ...
1  | abc  | 35          | optional 2    | ...
1  | abc  | 36          | optional 3    | ...
1  | abc  | 37          | optional 4    | ...
2  | qwe  | 34          | optional 1    | ...
2  | qwe  | 35          | optional 2    | ...
2  | qwe  | 36          | optional 3    | ...

我需要的是使用每个对象的记录获得不同的结果,在此示例中为'abc'和'qwe',以及包含每个对象的所有optional_name的OPTIONALS列。

对我来说输出类型(JSON,XML,查询输出)

并不重要

我尝试'分组',但我没有得到理想的结果。

3 个答案:

答案 0 :(得分:1)

一种解决方案是使用FOR XML组合每个组的行:

CREATE TABLE #testdata (ID int, NAME varchar(3), OPTIONAL_ID int, OPTIONAL_NAME varchar(10));
INSERT INTO #testdata (ID, NAME, OPTIONAL_ID, OPTIONAL_NAME) VALUES
    (1, 'abc', 34, 'optional 1'),
    (1, 'abc', 35, 'optional 2'),
    (1, 'abc', 36, 'optional 3'),
    (1, 'abc', 37, 'optional 4'),
    (2, 'qwe', 34, 'optional 1'),
    (2, 'qwe', 35, 'optional 2'),
    (2, 'qwe', 36, 'optional 3');

WITH names AS (
    SELECT DISTINCT NAME
    FROM #testdata
)
SELECT *
FROM names
CROSS APPLY (
    SELECT OPTIONAL_NAME
    FROM #testdata
    WHERE names.NAME = #testdata.NAME
    FOR XML PATH(''), ROOT('OPTIONAL_NAMES'), TYPE
) AS ca(xmldata)

Query Result

对于查询输出中的逗号分隔列表,请使用:

SELECT names.NAME, STUFF(xmldata, 1, 1, '')
FROM names
CROSS APPLY (
    SELECT ',' + OPTIONAL_NAME
    FROM #testdata
    WHERE names.NAME = #testdata.NAME
    FOR XML PATH('')
) AS ca(xmldata)

答案 1 :(得分:1)

试试这个(我只考虑了相关的专栏):

declare @table table (name char(3), optional_name char(10))
insert into @table values
('abc', 'optional 1'),
('abc', 'optional 2'),
('abc', 'optional 3'),
('abc', 'optional 4'),
('qwe', 'optional 1'),
('qwe', 'optional 2'),
('qwe', 'optional 3')

select name,
       (select optional_name from @table where name = T.name for xml path(''), type)
from @table [T]
group by name

如果您需要JSON,请在上次查询中将XML替换为JSON(需要最新的SQL Server)。

另一个选项(稍微修改过上一个查询):

select name,
       (select optional_name + ', ' from @table where name = T.name for xml path(''), type).value('(/)[1]','varchar(2000)') [optional_name]
from @table [T]
group by name

答案 2 :(得分:0)

XML解决方案看起来像......

测试数据

CREATE TABLE #temp (ID INT , NAME VARCHAR(20), OPTIONAL_ID INT 
                    ,  OPTIONAL_NAME VARCHAR(20), OTHER_FIELDS VARCHAR(20))

INSERT INTO #temp VALUES 
(1  ,'abc'  , 34  ,'optional 1' , 'Some Data' ),
(1  ,'abc'  , 35  ,'optional 2' , 'Some Data' ),
(1  ,'abc'  , 36  ,'optional 3' , 'Some Data' ),
(1  ,'abc'  , 37  ,'optional 4' , 'Some Data' ),
(2  ,'qwe'  , 34  ,'optional 1' , 'Some Data' ),
(2  ,'qwe'  , 35  ,'optional 2' , 'Some Data' ),
(2  ,'qwe'  , 36  ,'optional 3' , 'Some Data' );

<强>查询

SELECT
           t.[ID] AS [@ID]
        ,  t.Name AS [@Name]
        , (  
            SELECT  t2.OPTIONAL_ID
                  , t2.OPTIONAL_NAME
                  , t2.OTHER_FIELDS
            FROM #temp t2
            WHERE t.ID = t2.ID
            FOR XML PATH('OPTIONALS') , TYPE
           )
FROM 
(
    SELECT DISTINCT [ID] , Name
    FROM #temp 
)t
FOR XML PATH('x')

XML OUTPUT

<x ID="1" Name="abc">
  <OPTIONALS>
    <OPTIONAL_ID>34</OPTIONAL_ID>
    <OPTIONAL_NAME>optional 1</OPTIONAL_NAME>
    <OTHER_FIELDS>Some Data</OTHER_FIELDS>
  </OPTIONALS>
  <OPTIONALS>
    <OPTIONAL_ID>35</OPTIONAL_ID>
    <OPTIONAL_NAME>optional 2</OPTIONAL_NAME>
    <OTHER_FIELDS>Some Data</OTHER_FIELDS>
  </OPTIONALS>
  <OPTIONALS>
    <OPTIONAL_ID>36</OPTIONAL_ID>
    <OPTIONAL_NAME>optional 3</OPTIONAL_NAME>
    <OTHER_FIELDS>Some Data</OTHER_FIELDS>
  </OPTIONALS>
  <OPTIONALS>
    <OPTIONAL_ID>37</OPTIONAL_ID>
    <OPTIONAL_NAME>optional 4</OPTIONAL_NAME>
    <OTHER_FIELDS>Some Data</OTHER_FIELDS>
  </OPTIONALS>
</x>
<x ID="2" Name="qwe">
  <OPTIONALS>
    <OPTIONAL_ID>34</OPTIONAL_ID>
    <OPTIONAL_NAME>optional 1</OPTIONAL_NAME>
    <OTHER_FIELDS>Some Data</OTHER_FIELDS>
  </OPTIONALS>
  <OPTIONALS>
    <OPTIONAL_ID>35</OPTIONAL_ID>
    <OPTIONAL_NAME>optional 2</OPTIONAL_NAME>
    <OTHER_FIELDS>Some Data</OTHER_FIELDS>
  </OPTIONALS>
  <OPTIONALS>
    <OPTIONAL_ID>36</OPTIONAL_ID>
    <OPTIONAL_NAME>optional 3</OPTIONAL_NAME>
    <OTHER_FIELDS>Some Data</OTHER_FIELDS>
  </OPTIONALS>
</x>