2010-03-04 92 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