【发布时间】:2011-11-20 14:56:49
【问题描述】:
我有一个奇怪的设计要求。这是我正在使用的示例表
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 列
显示父级的 sCode nNestLevel 为 1 的原始键(有一个例外,将到达 一点点),如果原始 ID 已经在 nNestLevel 为 1 或 0 它应该再次打印与第一列相同的 sCode。
第 3 列
显示原始父级的sCode nNestLevel 为 0 的键(有一个例外,将在 一点),如果原始 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
【问题讨论】:
-
您能否澄清一下:
Show the the sCode of the parent of the original key that has a nNestLevel of 1 (with a exception, will get to that in a bit), if the original ID is allready at a nNestLevel of 1 or 0 it should print the same sCode again as the first column.如果原始键的 sCode 为 1,孩子应该在单独的列中显示父母的 sCode 还是应该再次显示相同的 sCode?span> -
@Wil sCode 是字符串描述。因此,如果作为 10283 的 forgen 密钥,第一列将是“健康计划诊断”,第二列将是“健康计划诊断”,第三列将是“诊断测试”,前两列是相同的,因为有低于 10283 的级别不足以拥有 3 个不同的名称。
标签: sql sql-server-2008 recursion recursive-query