2014-10-29 82 views
0

我有這個示例表。FOR XML PATH - 動態節點?

rate_id | ACCOUNT_ID |定義|類別| pmpm_override |量

1 | A1 | PSPM | C1 |空| 100

2 | A1 | PSPM | C2 |空| 200

3 | A1 | PC | C3 |空| 150

4 | A1 | PC | C4 |空| 250

5 | A2 | PMPM | C5 | TRUE | 400

6 | A2 | PMPM | C3 | TRUE | 500

7 | A3 | PMPM | C2 | FALSE | 600

的問題的重點是作爲它的值的 '定義' 列確定的節點名稱的元件類,金額和pmpm_override在下。

例如,當界定= PSPM節點是pspmrate,當定義= PC節點PCRATE等

使用FOR XML PATH我期待返回如下:

<?xml version="1.0" encoding="utf-8"?> 
<Rates> 
    <rate_id id="1"> 
    <account_id>a1</account_id> 
    <pspmrate> 
     <category>c1</category> 
     <amount>100</amount> 
    </pspmrate> 
    </rate_id> 
    <rate_id id="2"> 
    <account_id>a1</account_id> 
    <pspmrate> 
     <category>c2</category> 
     <amount>200</amount> 
    </pspmrate> 
    </rate_id> 
    <rate_id id="3"> 
    <account_id>a1</account_id> 
    <pcrate> 
     <category>c3</category> 
     <amount>150</amount>   
    </pcrate> 
    </rate_id> 
    <rate_id id="4"> 
    <account_id>a1</account_id> 
    <pcrate> 
     <category>c4</category> 
     <amount>250</amount>   
    </pcrate> 
    </rate_id> 
    <rate_id id="5"> 
    <account_id>a2</account_id> 
    <pmpmrate> 
     <category>c5</category> 
     <amount>400</amount>   
     <pmpm_override>true</pmpm_override> 
    </pmpmrate> 
    </rate_id> 
    <rate_id id="6"> 
    <account_id>a2</account_id> 
    <pmpmrate> 
     <category>c3</category> 
     <amount>500</amount>   
     <pmpm_override>true</pmpm_override> 
    </pmpmrate> 
    </rate_id> 
    <rate_id id="7"> 
    <account_id>a3</account_id> 
    <pmpmrate> 
     <category>c2</category> 
     <amount>600</amount>   
     <pmpm_override>false</pmpm_override> 
    </pmpmrate> 
    </rate_id> 
</Rates> 

對於現在我有一個查詢返回正確的結構減去節點名稱(我用FOR XML PATH('pspmrate')硬編碼),所以速率ID 3-7有錯誤的節點。

在現實中,查詢代碼要大得多,結構稍微複雜一些,但是這個例子代表了我正在尋找的東西 - 我想有辦法用動態sql執行此操作,但我試圖以避免在可能的情況下工作並排除龐大的查詢字符串。

我想我正在尋找一種方法來動態確定XML PATH。

任何建議表示讚賞。

謝謝。

回答

0

我想你可以用一個CASE表達式,如果你有一個已知的一些定義做到這一點:

SELECT [@id] = rate_id, 
     account_id, 
     CASE definition 
      WHEN 'PC' THEN (SELECT pmpm_override, amount, category FOR XML PATH('pcrate'), TYPE) 
      WHEN 'PMPM' THEN (SELECT pmpm_override, amount, category FOR XML PATH('pmpmrate'), TYPE) 
      WHEN 'PSPM' THEN (SELECT pmpm_override, amount, category FOR XML PATH('pspmrate'), TYPE) 
     END 
FROM T 
FOR XML PATH('rate_id'), ROOT('rates'); 

如果沒有,那麼你就需要動態SQL來建立你的CASE表達式:

DECLARE @SQL NVARCHAR(MAX); 
SELECT @SQL = 'SELECT [@id] = rate_id, 
         account_id, 
         CASE definition 
          ' + (SELECT 'WHEN ''' + Definition + 
             ''' THEN (SELECT pmpm_override, amount, category FOR XML PATH(''' + 
             LOWER(Definition) + 'rate''), TYPE) ' 
           FROM T 
           GROUP BY Definition 
           FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') + ' 
         END 
       FROM T 
       FOR XML PATH(''rate_id''), ROOT(''rates'');'; 

EXECUTE sp_executesql @SQL; 
+0

GarethD感謝您的反饋。確實存在有限數量的「定義」值(5)。我認爲某種類型的病例陳述可能是一種方式,我會嘗試你的第一個建議。我想我對此的保留是,在每個WHEN語句中,實際上有很多子查詢(未包含在樣例中)用於其他結構化元素,這些元素在每個「定義」節點中都是相同的。那些只會讓我的查詢變大!我會試一試!謝謝! – 2014-10-29 19:45:42

+0

如果您多次重複相同的子查詢,那麼您可以通過將邏輯封裝在公用表表達式中來簡化操作,並重用 – GarethD 2014-10-29 20:57:04