2010-03-04 96 views
4

我需要能够查询SharePoint数据库的调查结果。我遇到问题的数据类型是“评分等级”值。因此,每个表格列中的数据代表了一整组子问题及其答案。T-SQL:分析字符串与多个分隔符

所以下面的是什么是在一列中找到一个例子:

1.我们的函数定义了可用性是如何测量在生产中的硬件/软件;#3#2。我们的功能(例如SLA)存在可用性阈值水平;#3#3。我们的功能在出现阈值违规时遵循定义的流程;#4#4。我们的功能收集并维护可用性数据;#4#5。比较分析有助于识别可用性数据的趋势;#4#6。操作级别协议(OLA's)指导我们与其他内部团队的交互;#4#

问题以分号结尾,它们的答案在两个#号内。所以第一个问题的答案是3.

当我导出调查结果时,它将每个问题的格式设置为列标题,并将答案设置为下面单元格中的值,这对于获得每个问题的平均值问题,并希望能够从SQL查询中复制。

但是,如果我可以将查询结果分成两列(问题,答案)......我会很激动。

任何帮助表示赞赏。

非常感谢

汉克斯托林斯

*****附录:**

这是我的版本astander的解决方案......再次感谢!

DECLARE @Table TABLE( 
     QuestionSource VARCHAR(50), 
     QA VARCHAR(5000) 
) 

DECLARE @ReturnTable TABLE( 
     QuestionSource VARCHAR(50), 
     Question VARCHAR(5000), 
     Answer int 
) 

DECLARE @XmlField XML, 
     @QuestionSource VARCHAR(50) 

INSERT INTO @Table SELECT 
'Availability' AS QuestionSource,CONVERT(varchar(5000),ntext1) FROM UserData WHERE tp_ContentType = 'My Survey' 
INSERT INTO @Table SELECT 
'Capacity' AS QuestionSource,CONVERT(varchar(5000),ntext2) FROM UserData WHERE tp_ContentType = 'My Survey' 

--SELECT * FROM @Table 

DECLARE Cur CURSOR FOR 
SELECT QuestionSource, 
     CAST(Val AS XML) XmlVal 
FROM ( 
      SELECT QuestionSource, 
      LEFT(Vals, LEN(Vals) - LEN('<option><q>')) Val 
      FROM ( 
         SELECT QuestionSource, 
          '<option><q>' + REPLACE(REPLACE(REPLACE(QA,'&','&amp;'), ';#','</q><a>'), '#', '</a></option><option><q>') Vals 
         FROM @Table 

        ) sub 
     ) sub 

OPEN Cur 
FETCH NEXT FROM Cur INTO @QuestionSource,@XmlField 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    INSERT INTO @ReturnTable 
    SELECT @QuestionSource, 
      T.split.query('q').value('.', 'nvarchar(max)') question, 
      T.split.query('a').value('.', 'nvarchar(max)') answer 
    FROM @XmlField.nodes('/option') T(split) 
    FETCH NEXT FROM Cur INTO @QuestionSource,@XmlField 
END 

CLOSE Cur 
DEALLOCATE Cur 

SELECT * FROM @ReturnTable 
+0

在使用该光标之前,我会掏出眼睛!我会在我的回答中使用基于集合的方法。 – 2010-03-04 18:28:21

回答

0

好的,让我们来看看。我不得不使用一个游标,因为这可能会更好地从像C#这样的编程语言中实现,但是在这里......使用Sql Server 2005,请尝试以下操作。让我知道你是否需要任何解释。

DECLARE @Table TABLE(
     QuestionSource VARCHAR(50), 
     QA VARCHAR(1000) 
) 

DECLARE @ReturnTable TABLE(
     QuestionSource VARCHAR(50), 
     Question VARCHAR(1000), 
     Answer VARCHAR(10) 
) 

DECLARE @XmlField XML, 
     @QuestionSource VARCHAR(40) 

INSERT INTO @Table SELECT 
'Availability','1. Our function has defined how Availability is measured the hardware/software in Production;#3#2. Availability threshold levels exist for our function (e.g., SLA''s);#3#3. Our function follows a defined process when there are threshold breaches;#4#4. Our function collects and maintains Availability data;#4#5. Comparative analysis helps identify trending with the Availability data;#4#6. Operating Level Agreements (OLA''s) guide our interaction with other internal teams;#4#' 
INSERT INTO @Table SELECT 
'Capacity', '1. Our function has defined how Availability is measured the hardware/software in Production;#1#2. Availability threshold levels exist for our function (e.g., SLA''s);#2#3. Our function follows a defined process when there are threshold breaches;#3#4. Our function collects and maintains Availability data;#4#5. Comparative analysis helps identify trending with the Availability data;#5#6. Operating Level Agreements (OLA''s) guide our interaction with other internal teams;#6#' 


DECLARE Cur CURSOR FOR 
SELECT QuestionSource, 
     CAST(Val AS XML) XmlVal 
FROM (
      SELECT QuestionSource, 
        LEFT(Vals, LEN(Vals) - LEN('<option><q>')) Val 
      FROM (
         SELECT QuestionSource, 
           '<option><q>' + REPLACE(REPLACE(QA, ';#','</q><a>'), '#', '</a></option><option><q>') Vals 
         FROM @Table 
        ) sub 
     ) sub 

OPEN Cur 
FETCH NEXT FROM Cur INTO @QuestionSource, @XmlField 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    INSERT INTO @ReturnTable 
    SELECT @QuestionSource, 
      T.split.query('q').value('.', 'nvarchar(max)') question, 
      T.split.query('a').value('.', 'nvarchar(max)') answer 
    FROM @XmlField.nodes('/option') T(split) 
    FETCH NEXT FROM Cur INTO @QuestionSource, @XmlField 
END 

CLOSE Cur 
DEALLOCATE Cur 

SELECT * 
FROM @ReturnTable 
+0

astander - 非常感谢,这是完美的我的需求。 – 2010-03-04 16:22:25

+0

astander - 现在,如果我有多列这些问题,我可以使用UNION从其他列中提取问题。因此,一列表示“可用性”,下一个“容量”,我如何添加另一列来确定数据来自哪组问题和答案? – 2010-03-04 16:55:19

+0

看看编辑过的答案,这是你的意思吗? – 2010-03-04 17:00:20

3

你必须有一个分裂的功能设置,但一旦你拥有了它,试试这个光标免费的解决方案:

I prefer the number table approach to split a string in TSQL

对于这种方法的工作,你需要做的这一个时间表设置:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number 
    INTO Numbers 
    FROM sys.objects s1 
    CROSS JOIN sys.objects s2 
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

一旦Numbers表格设置,创建此分割功能,这将返回空字符串和行号:

CREATE FUNCTION [dbo].[FN_ListToTableRows] 
(
    @SplitOn char(1)  --REQUIRED, the character to split the @List string on 
    ,@List  varchar(8000)--REQUIRED, the list to split apart 
) 
RETURNS TABLE 
AS 
RETURN 
(

    ---------------- 
    --SINGLE QUERY-- --this WILL return empty rows 
    ---------------- 
    SELECT 
     ROW_NUMBER() OVER(ORDER BY number) AS RowNumber 
      ,LTRIM(RTRIM(SUBSTRING(ListValue, number+1, CHARINDEX(@SplitOn, ListValue, number+1)-number - 1))) AS ListValue 
     FROM (
       SELECT @SplitOn + @List + @SplitOn AS ListValue 
      ) AS InnerQuery 
      INNER JOIN Numbers n ON n.Number < LEN(InnerQuery.ListValue) 
     WHERE SUBSTRING(ListValue, number, 1) = @SplitOn 
); 
GO 

您现在可以轻松地拆分CSV字符串转换成表格,并加入就可以了,注意这种分裂,函数返回空字符串和行号:

select * from dbo.FN_ListToTableRows(',','1,2,3,,,4,5,6777,,,') 

OUTPUT:

RowNumber   ListValue 
-------------------- ------------ 
1     1 
2     2 
3     3 
4      
5      
6     4 
7     5 
8     6777 
9      
10     
11     

(11 row(s) affected) 

您现在可以使用CROSS APPLY来分割表格中的每一行,例如:

DECLARE @YourTable table (RowID int, RowValue varchar(8000)) 
INSERT INTO @YourTable VALUES (1,'1. Our function has defined how Availability is measured the hardware/software in Production;#3#2. Availability threshold levels exist for our function (e.g., SLA''s);#3#3. Our function follows a defined process when there are threshold breaches;#4#4. Our function collects and maintains Availability data;#4#5. Comparative analysis helps identify trending with the Availability data;#4#6. Operating Level Agreements (OLA''s) guide our interaction with other internal teams;#4#') 
INSERT INTO @YourTable VALUES (2,'1. one;#1#2. two;#2#3. three;#3#') 
INSERT INTO @YourTable VALUES (3,'1. aaa;#1#2. bbb;#2#3. ccc;#3#') 

;WITH AllRows As 
(
SELECT 
    o.RowID,st.RowNumber,st.ListValue AS RowValue 
    FROM @YourTable o 
     CROSS APPLY dbo.FN_ListToTableRows('#',LEFT(o.RowValue,LEN(o.RowValue)-1)) AS st 
) 
SELECT 
    a.RowID,a.RowValue AS Question, b.RowValue AS Answer 
    FROM AllRows     a 
     LEFT OUTER JOIN AllRows b ON a.RowID=b.RowID AND a.RowNumber+1=b.RowNumber 
    WHERE a.RowNumber % 2 = 1 

输出:

RowID  Question                      Answer 
----------- ----------------------------------------------------------------------------------------------- ------- 
1   1. Our function has defined how Availability is measured the hardware/software in Production; 3 
1   2. Availability threshold levels exist for our function (e.g., SLA's);       3 
1   3. Our function follows a defined process when there are threshold breaches;     4 
1   4. Our function collects and maintains Availability data;          4 
1   5. Comparative analysis helps identify trending with the Availability data;      4 
1   6. Operating Level Agreements (OLA's) guide our interaction with other internal teams;   4 
2   1. one;                       1 
2   2. two;                       2 
2   3. three;                      3 
3   1. aaa;                       1 
3   2. bbb;                       2 
3   3. ccc;                       3 

(12 row(s) affected) 
+0

感谢您的答复KM,我最终以斯坦德的回答 – 2010-03-04 16:21:46