SQL-SERVER:正确使用ISNULL返回默认值

时间:2014-06-18 17:04:52

标签: sql-server

我有多个查询绑在一起,生成排名列表,然后从每个查询中选择顶部。我的问题是我的最终SELECT中的T4.area可以为空并且可能返回null,所以我试图设置默认值'TBD'。

如果我自己打破查询并运行下面的命令,它运行正常:

SELECT ISNULL(MAX(area),'TBD') AS MDC FROM MDCcte3 WHERE row = 5

但是在我的主查询中包含它,如下所示不会返回结果:

SELECT T1.area as Growth, T2.area AS Efficiency, T3.area as Risk, ISNULL(T4.area,'TBD') as MDC FROM Gcte3 T1, Ecte3 T2, Rcte3 T3, MDCcte3 T4 WHERE T1.row = 1 AND T2.row = 1 AND T3.row = 1 AND T4.row = 5 GROUP BY T1.area, T2.area, T3.area, T4.area


    declare @MainHospital varchar(50)='Hospital1';

--GROWTH AREA RANK
WITH Gcte AS (
SELECT 4 score, growth1 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 3 score, growth2 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 2 score, growth3 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 1 score, growth4 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 0 score, growth5 area FROM Survey
WHERE MainHospital = @MainHospital
),

Gcte2 AS (
SELECT area, SUM(score) score FROM Gcte
GROUP BY area
HAVING area IS NOT NULL                                   
),

Gcte3 AS (
SELECT area, score, 
Row_Number() OVER (ORDER BY score DESC) row,
RANK() OVER (ORDER BY score DESC) rank
FROM Gcte2
),                                 

--EFFICIENCY AREA RANK
Ecte AS (
SELECT 4 score, Efficiency1 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 3 score, Efficiency2 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 2 score, Efficiency3 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 1 score, Efficiency4 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 0 score, Efficiency5 area FROM Survey
WHERE MainHospital = @MainHospital
),

Ecte2 AS (
SELECT area, SUM(score) score FROM Ecte
GROUP BY area
HAVING area IS NOT NULL                                  
),

Ecte3 AS (
SELECT area, score, 
Row_Number() OVER (ORDER BY score DESC) row,
RANK() OVER (ORDER BY score DESC) rank
FROM Ecte2
),

--RISK AREA RANK
Rcte AS (
SELECT 4 score, Risk1 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 3 score, Risk2 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 2 score, Risk3 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 1 score, Risk4 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 0 score, Risk5 area FROM Survey
WHERE MainHospital = @MainHospital
),

Rcte2 AS (
SELECT area, SUM(score) score FROM Rcte
GROUP BY area
HAVING area IS NOT NULL                                  
),

Rcte3 AS (
SELECT area, score, 
Row_Number() OVER (ORDER BY score DESC) row,
RANK() OVER (ORDER BY score DESC) rank
FROM Rcte2
),

--ALL MDC'S FOR GER RANK
MDCcte AS (
SELECT 2 score, GrowthMDC1 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL                                 
SELECT 1 score, GrowthMDC2 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 0 score, GrowthMDC3 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 2 score, EfficiencyMDC1 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 1 score, EfficiencyMDC2 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 0 score, EfficiencyMDC3 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 2 score, RiskMDC1 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 1 score, RiskMDC2 area FROM Survey
WHERE MainHospital = @MainHospital
UNION ALL
SELECT 0 score, RiskMDC3 area FROM Survey
WHERE MainHospital = @MainHospital                                   
),

MDCcte2 AS (
SELECT area, SUM(score) score FROM  MDCcte
GROUP BY area
HAVING area IS NOT NULL                                 
),

MDCcte3 AS (
SELECT area, score,
Row_Number() OVER (ORDER BY score DESC) as row, 
RANK() OVER (ORDER BY score DESC) rank
FROM  MDCcte2
)




 SELECT T1.area as Growth, T2.area AS Efficiency, T3.area as Risk, ISNULL(T4.area,'TBD') as MDC 
FROM Gcte3 T1, Ecte3 T2, Rcte3 T3, MDCcte3 T4
WHERE T1.row = 1 AND T2.row = 1 AND T3.row = 1 AND T4.row = 4
GROUP BY T1.area, T2.area, T3.area, T4.area

1 个答案:

答案 0 :(得分:0)

也可能需要TBD。

SELECT T1.area as Growth, T2.area AS Efficiency, T3.area as Risk, ISNULL(T4.area,'TBD') as MDC 
FROM Gcte3 T1, Ecte3 T2, Rcte3 T3, MDCcte3 T4
WHERE T1.row = 1 AND T2.row = 1 AND T3.row = 1 AND (T4.row = 5 or t4.row is null)
GROUP BY T1.area, T2.area, T3.area, ISNULL(T4.area,'TBD')

我真的不喜欢处理连接的方式,因为它会导致性能不佳,因为数据库必须在过滤器之前生成笛卡尔,但是如果没有性能问题。 耸肩,这不是问题的一部分。

我真的认为你应该加入这个......表格是否与彼此相关?

SELECT T1.area as Growth, T2.area AS Efficiency, T3.area as Risk, ISNULL(T4.area,'TBD') as MDC 
FROM Gcte3 T1, 
LEFT JOIN Ecte3 T2
 on T1.Row = T2.Row 
LEFT JOIN Rcte3 T3
 on T2.Trow = T3.Row
LEFT JOIN MDCcte3 T4
 on T3.Row = T4.Row and T4.Row = 5
WHERE T1.row = 1
GROUP BY T1.area, T2.area, T3.area, ISNULL(T4.area,'TBD')

这可能有用,但我真的需要看T1,T2,T3和T4中的样本数据,以便更好地理解你所追求的困境和预期结果。

至于为什么它在您的单个查询中起作用而在组中不起作用。 单个查询返回最大值,如果找不到一个,则返回第5行的TBD,它不必与Joins竞争。

当您加入记录时,每个记录首先与另一个记录相结合。

因此,如果T1有10条记录,T2有10条记录,T3有10条记录,T4有5条... 生成10 * 10 * 10 * 5行5000然后数据库引擎过滤出T1.row<>的行。 1 T2.row<> 2和T3.row<> 1。 然后你说要过滤那些T4.Row<> 5.没有第五行。所以没有回复记录。

这就是为什么我认为左连接会更好地工作,因为它将返回上一个表中的所有记录,只有那些匹配,然后你的NULLS被处理为T4.Area的TBD。

但为了使这个工作,表格必须与某些东西有关;到目前为止,没有说明它们之间的关系。