2011-10-27 51 views
0

我想基於最大值或最小值來聚合行,其中最大/最小值由業務規則而不是固有值確定。換句話說,我需要創建一個自定義的最大/最小值 - 不使用CLR。我在下面的代碼片段中有一個獨立工作的例子,但我覺得必須有一個更簡單的方法。查找最大/最小任意優先級

在這種特殊情況下,我需要IPA列的業務優先級由以下[IPAMap] CTE中顯示的[Seq]值定義。然後,我從[TestData] table/cte(本示例中只有四行)中取任意一組行,並根據優先級將它們聚合成兩行,並選擇適當的IPA值。

--Table [IPAMap] holds all possible values for [IPA], and reflects the relative 
--'priority' of each with the [Seq] column. This table is used as a lookup for 
--business rules. 
;WITH IPAMap (Seq, IPA) AS ( 
SELECT 1, 'Q' UNION ALL 
SELECT 2, 'S' UNION ALL 
SELECT 3, 'A' UNION ALL 
SELECT 4, 'L' 
) 
--Table [TestData] represents the real data. 
, TestData (CustomerID, IPA) AS ( 
SELECT '123', 'A' UNION ALL 
SELECT '123', 'S' UNION ALL 
SELECT '234', 'L' UNION ALL 
SELECT '234', 'Q' 
) 
--Table [PartyIPASeq] finds the lowest Seq rank from [TestData] 
,PartyIPASeq (CustomerID, IPASeq) AS ( 
SELECT 
    CustomerID, 
    MIN(IP.Seq) 
FROM TestData [TD] 
    INNER JOIN IPAMap [IP] ON IP.IPA = TD.IPA 
    GROUP BY CustomerID 
) 
--The final selection provides the key and the 'IPA' with the lowest rank 
SELECT TD.CustomerID, TD.IPA 
FROM TestData [TD] 
INNER JOIN IPAMap [IP] ON IP.IPA = TD.IPA 
INNER JOIN PartyIPASeq [SEQ] ON SEQ.CustomerID = [TD].CustomerID 
    AND SEQ.IPASeq = IP.Seq 

上述查詢的結果是這樣的:

CustomerID IPA 
234   S 
123   Q 

這是正確的,但我希望有人能告訴我一個更簡單的方法來完成同樣的工作。

+0

你的'DISTINCT'是多餘的。使用'GROUP BY'可以保證結果集中的行是不同的。 –

+0

@Mark:固定 - 刪除它。 –

+0

你可以在聚集中使用CASE語句,MIN(CASE MA.IPA WHEN 3 THEN 7 WHEN 4 THEN 6等)但是我懷疑這是簡單得多還是高性能的,除了導致稍微簡單的執行計劃。如果映射不改變,爲什麼不把它們放在永久性的桌子上? – carpii

回答

0

貌似答案是使用窗口函數與CHARINDEX的訂單通過,像這樣:

WITH TestData (CustomerID, IPA) AS ( 
    SELECT '123', 'A' UNION ALL 
    SELECT '123', 'S' UNION ALL 
    SELECT '234', 'L' UNION ALL 
    SELECT '234', 'Q' 
    ) 
SELECT CustomerID, IPA 
FROM (
     SELECT CustomerID, 
     IPA, 
     ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY CHARINDEX(IPA, 'QSAL')) rownum 
     FROM TestData 
    ) A 
WHERE rownum = 1 

如果業務數據採用多字符值,則CHARINDEX被替換爲PATINDEX功能。