2011-09-19 104 views
1

我有一些奇怪的設計要求。這裏是我正在使用的示例表遞歸SQL來填充數列的值

DECLARE @T TABLE 
(
kID INT, 
sCode VARCHAR(50), 
kParentID INT NULL, 
nNestLevel INT 
) 

INSERT INTO @T 
SELECT 10009,'Professional Fees    ',NULL ,0 UNION ALL 
SELECT 10371,'Exam Room Fees     ',10009 ,1 UNION ALL 
SELECT 10410,'Diagnostic Tests    ',NULL ,0 UNION ALL 
SELECT 10011,'Pharmacy Income    ',NULL ,0 UNION ALL 
SELECT 10395,'Dietary Products    ',NULL ,0 UNION ALL 
SELECT 10053,'Outpatient Services & Treatment',10371 ,2 UNION ALL 
SELECT 10055,'Canine Vaccines    ',10371 ,2 UNION ALL 
SELECT 10200,'Office Calls and Exams   ',10371 ,2 UNION ALL 
SELECT 10204,'Feline Vaccines    ',10371 ,2 UNION ALL 
SELECT 10205,'Ferret Vaccines    ',10371 ,2 UNION ALL 
SELECT 10206,'Euthanasia      ',10371 ,2 UNION ALL 
SELECT 10207,'Cremation & Burial    ',10371 ,2 UNION ALL 
SELECT 10304,'Laser Therapy     ',10371 ,2 UNION ALL 
SELECT 10379,'Hospitalization & Inpatient Ser',10371 ,2 UNION ALL 
SELECT 10283,'Wellness Plan Diagnostics  ',10410 ,1 UNION ALL 
SELECT 10411,'Opthalmic Tests    ',10410 ,1 UNION ALL 
SELECT 10412,'Blood Pressure     ',10410 ,1 UNION ALL 
SELECT 10413,'Diagnostic Other Tests   ',10410 ,1 UNION ALL 
SELECT 10414,'EKG       ',10410 ,1 UNION ALL 
SELECT 10267,'In Hospital Pharmacy   ',10011 ,1 UNION ALL 
SELECT 10368,'Parasiticides     ',10011 ,1 UNION ALL 
SELECT 10383,'Outpatient Pharmacy   ',10011 ,1 UNION ALL 
SELECT 10013,'Prescription Diets    ',10395 ,1 UNION ALL 
SELECT 10021,'Non Prescription Diets   ',10395 ,1 UNION ALL 
SELECT 10083,'Inpatient Medical Services & Tx',10379 ,3 UNION ALL 
SELECT 10201,'Outpatient Treatments   ',10053 ,3 UNION ALL 
SELECT 10280,'Herbal & Acupuncture Exams  ',10200 ,3 UNION ALL 
SELECT 10295,'Hospital Tasks Income   ',10379 ,3 UNION ALL 
SELECT 10308,'Distemper/Parvo    ',10055 ,3 UNION ALL 
SELECT 10309,'Bordetella      ',10055 ,3 

每個項目都會指向它的下一級別的父項。我需要做的是基於引用這一項,並使用兒童作爲外鍵,我需要三列添加到表中的另一表的查詢,

列1

展外鍵的SCODE,

列2

顯示日e 原始密鑰的父節點的sCode,其nNestLevel爲1(例外情況,將在一點內得到 ),如果原始ID已經在nNestLevel爲1或 0處,它應該打印與第一列相同的sCode。

列3

顯示有0 nNestLevel原 密鑰的母的的SCODE(有例外,將獲得在 位),如果原始ID已經在0的nNestLevel準備好了,應該 再次打印與第一列相同的sCode。


我摸索周圍做遞歸查詢窗口,我開始明白如何做到這一點,但問題是有一個例外,那是扔我送行的規則:

如果根父親kID是10009,則使用nNestLevel 1和2而不是0 ,對於最後兩列的規則使用1。

我不知道該如何處理這種特殊情況。


我的解決方案

這是基於關閉馬丁·史密斯的答案的解決方案。做了一些小的改動。第一個CTE沒有正確傳遞baseID。最終查詢中的select語句還需要進行調整,以便case語句在返回Null之前返回正確的列。

;WITH R AS 
(
SELECT * , 1 AS L, kID AS BasekID 
FROM Accounts 
UNION ALL 
SELECT T.*, L+1, R.BasekID 
FROM Accounts T JOIN R ON T.kID = R.kParentID 
), T AS 
(
SELECT BasekID AS kID, 
     MAX(CASE WHEN L=1 THEN sCode END) AS sCode, 
     MAX(CASE WHEN L=1 THEN nNestLevel END) AS nNestLevel,  
     MAX(CASE WHEN nNestLevel =0 THEN sCode END) AS sCode0, 
     MAX(CASE WHEN nNestLevel =1 THEN sCode END) AS sCode1, 
     MAX(CASE WHEN nNestLevel =2 THEN sCode END) AS sCode2, 
     MAX(CASE WHEN nNestLevel =0 THEN kID END) AS RootkID 
FROM R 
GROUP BY BasekID 
) 
    SELECT kID, sCode AS Col1, 
     --This case statement is to handel when the rootkID is 10009, we should go up a level if it is. 
    CASE WHEN nNestLevel <= 1 AND RootkID <> 10009 THEN sCode 
     WHEN nNestLevel <= 2 AND RootkID = 10009 THEN sCode 
     WHEN RootkID = 10009 THEN sCode2 
     ELSE sCode1 END AS Col2, 
    CASE WHEN nNestLevel <= 0 AND RootkID <> 10009 THEN sCode 
     WHEN nNestLevel <= 1 AND RootkID = 10009 THEN sCode 
     WHEN RootkID = 10009 THEN sCode1 
     ELSE sCode0 END AS Col3 
FROM T 
+0

你能澄清這一點:'顯示的是具有1 nNestLevel原始密鑰的母的的SCODE(有例外,將獲得在一個位),如果原來的ID是媒體鏈接在一個1或0的nNestLevel它應該再次打印與第一列相同的sCode。如果原始密鑰的sCode爲1,孩子應該在單獨的列中顯示父代的s代碼,還是應該再次顯示相同的s代碼? – Wil

+0

@Wil sCode是字符串描述。因此,如果作爲10283的原始密鑰,第一列將是「健康計劃診斷」,第二列將是「健康計劃診斷」,第三列將是「診斷測試」,前兩列是相同的,因爲那裏10283以下的級別不足以擁有3個不同的名稱。 –

回答

1

我覺得像這樣的東西應該工作。可能不完全正確,但我會讓你排序一個!

;WITH R AS 
(
SELECT * , 1 AS L, kID AS BasekID 
FROM @T 
UNION ALL 
SELECT T.*, L+1, R.kID 
FROM @T T JOIN R ON T.kID = R.kParentID 
), T AS 
(
SELECT BasekID AS kID, 
     MAX(CASE WHEN L=1 THEN sCode END) AS sCode, 
     MAX(CASE WHEN L=1 THEN nNestLevel END) AS nNestLevel,  
     MAX(CASE WHEN nNestLevel =0 THEN sCode END) AS sCode0, 
     MAX(CASE WHEN nNestLevel =1 THEN sCode END) AS sCode1, 
     MAX(CASE WHEN nNestLevel =2 THEN sCode END) AS sCode2, 
     MAX(CASE WHEN nNestLevel =0 THEN kID END) AS RootkID 
FROM R 
GROUP BY BasekID 
) 
    SELECT sCode AS Col1, 
     CASE WHEN nNestLevel <=1 AND RootkID <> 10009 THEN sCode 
      WHEN nNestLevel <=1 AND RootkID = 10009 THEN sCode2 
      ELSE sCode1 END AS Col2, 
     CASE WHEN nNestLevel =0 AND RootkID <> 10009 THEN sCode 
      WHEN nNestLevel =0 AND RootkID = 10009 THEN sCode1 
      ELSE sCode0 END AS Col3 
FROM T 
+1

我遇到的問題是R塊,每個迭代的BaseID都基於前一個迭代的kID。我需要的是它是L = 1的KID。爲了解決這個問題,我把'SELECT T. *,L + 1,R.kID'改成了'SELECT T. *,L + 1,R.BasekID'。還有我在10009案件中遇到了一些問題。我會用完成的查詢更新我的OP,但會給你正確的答案。 –