将单字段SQL输出转换为不同的字段

时间:2018-08-15 18:04:59

标签: sql sql-server ssms

我有一项业务要求,将SQL输出修改为不同的字段。

例如,我有一个表格SurveyResults并将问题和答案记录在单列中。

select * from SurveyResults 

输出:

+-----------------+-------+------------+-----------------------+-----------+------------+-------------------------+-------------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| ApplicationName | DNIS  |  Provider  | AgentPeripheralNumber | PlanName  | CaseNumber |        StartTime        |         EndTime         |                     CallId                     |                                               Results                                               |
+-----------------+-------+------------+-----------------------+-----------+------------+-------------------------+-------------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| AgentSurvey     | 20xxx | 860xxxxxxx |                 2xxxx | xxxxx     | NULL       | 2018-08-16 13:33:05.390 | 2018-08-16 13:33:22.127 | 10.xxx.xxx.xx.1534440785204.634158.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
| AgentSurvey     | 20xxx | 508xxxxxxx |                 2xxxx | xxxxxx    | NULL       | 2018-08-16 13:32:50.500 | 2018-08-16 13:33:11.643 | 10.xxx.xxx.xx.1534440770297.634125.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
| AgentSurvey     | 20xxx | 408xxxxxxx |                 2xxxx | xxxxxxxxx | D1096xxxxx | 2018-08-16 13:32:39.240 | 2018-08-16 13:32:57.630 | 10.xxx.xxx.xx.1534440759224.640875.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
| AgentSurvey     | 20xxx | 860xxxxxxx |                 2xxxx | xxxxx     | NULL       | 2018-08-16 13:32:12.217 | 2018-08-16 13:32:14.310 | 10.xxx.xxx.xx.1534440732030.634018.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
+-----------------+-------+------------+-----------------------+-----------+------------+-------------------------+-------------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+

现在,企业希望在多列中查看此数据。像下面这样。

输出:

提供商DNIS Q1 Q2 Q3 Q4

XXXXXX 2XXXX Phy .. sat .. other .. res .. XXXXXX 2XXXX phy .. case .. null

我可以通过简单地修改我的表来做到这一点,但是我做不到,因为它依赖于不同的应用程序,这将是一项繁琐的任务。

使用您的查询:

SELECT sr.CallId,sr.PlanName,sr.Provider,sr.CaseNumber,sr.StartTime
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q1"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q1
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q2"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q2
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q3"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q3
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q4"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q4
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q4a"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q4a
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q5"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q5
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q6"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q6
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q6a"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q6a
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q7"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q7
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q8"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q8
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q9"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q9
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q10"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q10
FROM SurveyResults sr
CROSS APPLY (

    -- convert [Results] to parsable xml --

    SELECT 
        CAST( '<qn><name>' + REPLACE( REPLACE( LEFT( Results, LEN( Results ) - 1 ), ':', '</name><val>' ), ';', '</val></qn><qn><name>' ) + '</val></qn>' AS XML ) AS qnXml
    FROM SurveyResults where [CallId] = sr.CallId

) AS qn
ORDER BY
StartTime desc;

立即获取此错误: 消息9411,第16级,状态1,第1行 XML解析:第1行,字符45,应使用分号

1 个答案:

答案 0 :(得分:1)

好的,让我从强制性的指导评论开始: 您确实需要规范化数据。

顺便说一句,这将是我处理您的情况的方法。您可以在SSMS中运行/修改此示例。

我要做的第一件事是创建一个(有点)与您的环境相匹配的示例环境:

DECLARE @SurveyResults TABLE ( [Results] VARCHAR(1000), [Id] INT IDENTITY (1,1) );

INSERT INTO @SurveyResults ( [Results] )
VALUES
( 'Q1:null;Q2:very_satisified;Q3:null;Q4:null;Q5:null;Q6:null;Q7:null;Q8:null;Q9:null;Q10:null;' )
, ( 'Q1:null;Q2:null;Q3:null;Q4:null;Q5:null;Q6:null;Q7:null;Q8:null;Q9:null;Q10:null;' )
, ( 'Q1:physician_office;Q2:satisfied;Q3:other_reason;Q4:resolution_no;Q5:timely_yes;Q6:website_yes;Q7:no_reply;Q8:null;Q9:null;Q10:null;' );

然后我从SurveyResults中查询结果XML:

SELECT
    sr.Id
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q1"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q1
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q2"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q2
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q3"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q3
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q4"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q4
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q5"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q5
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q6"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q6
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q7"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q7
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q8"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q8
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q9"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q9
    , NULLIF( qn.qnXml.value( 'data(//qn[name="Q10"]/val)[1]', 'VARCHAR(50)' ), 'null' ) AS Q10
FROM @SurveyResults sr
CROSS APPLY (

    -- convert [Results] to parsable xml --

    SELECT 
        CAST( '<qn><name>' + REPLACE( REPLACE( LEFT( Results, LEN( Results ) - 1 ), ':', '</name><val>' ), ';', '</val></qn><qn><name>' ) + '</val></qn>' AS XML ) AS qnXml
    FROM @SurveyResults WHERE [Id] = sr.Id

) AS qn
ORDER BY
    [Id];

返回:

+----+------------------+-----------------+--------------+---------------+------------+-------------+----------+------+------+------+
| Id |        Q1        |       Q2        |      Q3      |      Q4       |     Q5     |     Q6      |    Q7    |  Q8  |  Q9  | Q10  |
+----+------------------+-----------------+--------------+---------------+------------+-------------+----------+------+------+------+
|  1 | NULL             | very_satisified | NULL         | NULL          | NULL       | NULL        | NULL     | NULL | NULL | NULL |
|  2 | NULL             | NULL            | NULL         | NULL          | NULL       | NULL        | NULL     | NULL | NULL | NULL |
|  3 | physician_office | satisfied       | other_reason | resolution_no | timely_yes | website_yes | no_reply | NULL | NULL | NULL |
+----+------------------+-----------------+--------------+---------------+------------+-------------+----------+------+------+------+

我的示例不包括您的“ Q4a”分支(或类似内容),并且做出了一些主要假设(例如,每个Result都有尾随的分号),但是,我认为这里已经足够让您入门。

基于新细节的更新(PST 2018年8月16日下午12:45)

/*
+-----------------+-------+------------+-----------------------+-----------+------------+-------------------------+-------------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| ApplicationName | DNIS  |  Provider  | AgentPeripheralNumber | PlanName  | CaseNumber |        StartTime        |         EndTime         |                     CallId                     |                                               Results                                               |
+-----------------+-------+------------+-----------------------+-----------+------------+-------------------------+-------------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| AgentSurvey     | 20xxx | 860xxxxxxx |                 2xxxx | xxxxx     | NULL       | 2018-08-16 13:33:05.390 | 2018-08-16 13:33:22.127 | 10.xxx.xxx.xx.1534440785204.634158.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
| AgentSurvey     | 20xxx | 508xxxxxxx |                 2xxxx | xxxxxx    | NULL       | 2018-08-16 13:32:50.500 | 2018-08-16 13:33:11.643 | 10.xxx.xxx.xx.1534440770297.634125.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
| AgentSurvey     | 20xxx | 408xxxxxxx |                 2xxxx | xxxxxxxxx | D1096xxxxx | 2018-08-16 13:32:39.240 | 2018-08-16 13:32:57.630 | 10.xxx.xxx.xx.1534440759224.640875.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
| AgentSurvey     | 20xxx | 860xxxxxxx |                 2xxxx | xxxxx     | NULL       | 2018-08-16 13:32:12.217 | 2018-08-16 13:32:14.310 | 10.xxx.xxx.xx.1534440732030.634018.AgentSurvey | Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null; |
+-----------------+-------+------------+-----------------------+-----------+------------+-------------------------+-------------------------+------------------------------------------------+-----------------------------------------------------------------------------------------------------+
*/

-- create table variable --

DECLARE @SurveyResults TABLE ( ApplicationName VARCHAR(50), DNIS VARCHAR(10), [Provider] VARCHAR(10), AgentPeripheralNumber VARCHAR(255), PlanName VARCHAR(10), CaseNumber VARCHAR(10), StartTime DATETIME, EndTime DATETIME, CallId VARCHAR(255), Results VARCHAR(1000) );

-- insert data --

INSERT INTO @SurveyResults (
    ApplicationName, DNIS, [Provider], AgentPeripheralNumber, PlanName, CaseNumber, StartTime, EndTime, CallId, Results
)
VALUES
  ( 'AgentSurvey', '20xxx', '860xxxxxxx', '                2xxxx', 'xxxxx', NULL, '2018-08-16 13:33:05.390', '2018-08-16 13:33:22.127', '10.xxx.xxx.xx.1534440785204.634158.AgentSurvey', 'Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null;' )
, ( 'AgentSurvey', '20xxx', '508xxxxxxx', '                2xxxx', 'xxxxxx', NULL, '2018-08-16 13:32:50.500', '2018-08-16 13:33:11.643', '10.xxx.xxx.xx.1534440770297.634125.AgentSurvey', 'Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null;' )
, ( 'AgentSurvey', '20xxx', '408xxxxxxx', '                2xxxx', 'xxxxxxxxx', 'D1096xxxxx', '2018-08-16 13:32:39.240', '2018-08-16 13:32:57.630', '10.xxx.xxx.xx.1534440759224.640875.AgentSurvey', 'Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null;' )
, ( 'AgentSurvey', '20xxx', '860xxxxxxx', '                2xxxx', 'xxxxx', NULL, '2018-08-16 13:32:12.217', '2018-08-16 13:32:14.310', '10.xxx.xxx.xx.1534440732030.634018.AgentSurvey', 'Q1:null;Q2:null;Q3:null;Q4:null;Q4a:null;Q5:null;Q6:null;Q6a:null;Q7:null;Q8:null;Q9:null;Q10:null;' )

-- preview data --

SELECT * FROM @SurveyResults ORDER BY StartTime;

-- query data --
-- removed NULLIFs for the sake of readability --

SELECT
    sr.CallId
    , qn.qnXml.value( 'data(//qn[name="Q1"]/val)[1]', 'VARCHAR(50)' ) AS Q1
    , qn.qnXml.value( 'data(//qn[name="Q1a"]/val)[1]', 'VARCHAR(50)' ) AS Q1a
    , qn.qnXml.value( 'data(//qn[name="Q2"]/val)[1]', 'VARCHAR(50)' ) AS Q2
    , qn.qnXml.value( 'data(//qn[name="Q2a"]/val)[1]', 'VARCHAR(50)' ) AS Q2a
    , qn.qnXml.value( 'data(//qn[name="Q3"]/val)[1]', 'VARCHAR(50)' ) AS Q3
    , qn.qnXml.value( 'data(//qn[name="Q3a"]/val)[1]', 'VARCHAR(50)' ) AS Q3a
    , qn.qnXml.value( 'data(//qn[name="Q4"]/val)[1]', 'VARCHAR(50)' ) AS Q4
    , qn.qnXml.value( 'data(//qn[name="Q4a"]/val)[1]', 'VARCHAR(50)' ) AS Q4a
    , qn.qnXml.value( 'data(//qn[name="Q5"]/val)[1]', 'VARCHAR(50)' ) AS Q5
    , qn.qnXml.value( 'data(//qn[name="Q5a"]/val)[1]', 'VARCHAR(50)' ) AS Q5a
    , qn.qnXml.value( 'data(//qn[name="Q6"]/val)[1]', 'VARCHAR(50)' ) AS Q6
    , qn.qnXml.value( 'data(//qn[name="Q6a"]/val)[1]', 'VARCHAR(50)' ) AS Q6a
    , qn.qnXml.value( 'data(//qn[name="Q7"]/val)[1]', 'VARCHAR(50)' ) AS Q7
    , qn.qnXml.value( 'data(//qn[name="Q7a"]/val)[1]', 'VARCHAR(50)' ) AS Q7a
    , qn.qnXml.value( 'data(//qn[name="Q8"]/val)[1]', 'VARCHAR(50)' ) AS Q8
    , qn.qnXml.value( 'data(//qn[name="Q8a"]/val)[1]', 'VARCHAR(50)' ) AS Q8a
    , qn.qnXml.value( 'data(//qn[name="Q9"]/val)[1]', 'VARCHAR(50)' ) AS Q9
    , qn.qnXml.value( 'data(//qn[name="Q9a"]/val)[1]', 'VARCHAR(50)' ) AS Q9a
    , qn.qnXml.value( 'data(//qn[name="Q10"]/val)[1]', 'VARCHAR(50)' ) AS Q10
    , qn.qnXml.value( 'data(//qn[name="Q10a"]/val)[1]', 'VARCHAR(50)' ) AS Q10a
FROM @SurveyResults sr
CROSS APPLY (
    -- convert [Results] to parsable xml --

    SELECT 
        CAST( '<qn><name>' + REPLACE( REPLACE( LEFT( Results, LEN( Results ) - 1 ), ':', '</name><val>' ), ';', '</val></qn><qn><name>' ) + '</val></qn>' AS XML ) AS qnXml
    FROM @SurveyResults where [CallId] = sr.CallId

) qn
ORDER BY
    sr.StartTime;

返回(按预期仅 4行):

+------------------------------------------------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
|                     CallId                     |  Q1  | Q1a  |  Q2  | Q2a  |  Q3  | Q3a  |  Q4  | Q4a  |  Q5  | Q5a  |  Q6  | Q6a  |  Q7  | Q7a  |  Q8  | Q8a  |  Q9  | Q9a  | Q10  | Q10a |
+------------------------------------------------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 10.xxx.xxx.xx.1534440732030.634018.AgentSurvey | null | NULL | null | NULL | null | NULL | null | null | null | NULL | null | null | null | NULL | null | NULL | null | NULL | null | NULL |
| 10.xxx.xxx.xx.1534440759224.640875.AgentSurvey | null | NULL | null | NULL | null | NULL | null | null | null | NULL | null | null | null | NULL | null | NULL | null | NULL | null | NULL |
| 10.xxx.xxx.xx.1534440770297.634125.AgentSurvey | null | NULL | null | NULL | null | NULL | null | null | null | NULL | null | null | null | NULL | null | NULL | null | NULL | null | NULL |
| 10.xxx.xxx.xx.1534440785204.634158.AgentSurvey | null | NULL | null | NULL | null | NULL | null | null | null | NULL | null | null | null | NULL | null | NULL | null | NULL | null | NULL |
+------------------------------------------------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+

这对我有用。