1

我有一个奇怪的设计要求。这是我正在使用的示例表

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

每个项目将指向它在下一级的父级。我需要进行一个基于另一个表的查询,该表引用该表并使用 kID 作为外键,我需要向该表添加三列,

第 1 列

显示外键的sCode,

第 2 栏

显示 nNestLevel 为 1 的原始键的父级的 sCode(有一个例外,稍后会介绍),如果原始 ID 已准备好 nNestLevel 为 1 或 0,它应该打印相同的 sCode再次作为第一列。

第 3 栏

显示 nNestLevel 为 0 的原始键的父级的 sCode(有一个例外,稍后会谈到),如果原始 ID 已经准备好 nNestLevel 为 0,它应该再次打印相同的 sCode第一列。


我正在摸索进行递归查找,我开始了解如何去做,但是问题是规则有一个例外让我失望:

如果根父 kID 为 10009,则使用 nNestLevel 1 和 2 而不是 0 和 1 作为最后两列的规则。

我不知道如何处理这种特殊情况。


我的解决方案

这是基于 Martin Smith 回答的解决方案。做了一些小的改动。第一个 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
4

1 回答 1

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
于 2011-09-19T22:27:23.823 回答