我想检查一下嵌套的情况,其中父级依赖于子级,是否有更好的方法将查询抛出到from子句中。
请注意逻辑的细节,但这是我想要完成的蓝图和它的工作。代码看起来很草率。是否有更好/更简洁的方法来实现这一目标?
SELECT
*,
CASE
WHEN b.NewCalcColRate IS NULL
THEN 0
ELSE b.NewCalcColRate * 1000
END AS FinalCalcColRate
FROM
(SELECT
a.*,
CASE
WHEN a.calcColRate IS NULL
THEN 0
ELSE a.calcColRate * 100
END AS NewCalcColRate
FROM
(SELECT
*,
CASE
WHEN f.AnnualCost IS NULL
THEN 0
ELSE f.AnnualCost / 12
END AS calcColRate
FROM
Rates) AS a
) AS b
答案 0 :(得分:3)
首先,NewCalcColRate
和calcColRate
永远不会是NULL
,因为在嵌套CASE
中,当NULL
CASE WHEN f.AnnualCost IS NULL THEN 0
时,您将其设置为0 f
1}}),这样逻辑就没有意义了。
此外,您的此列包含Rate
引用,但该子查询中的SELECT
*,
CASE
WHEN AnnualCost IS NULL
THEN 0
ELSE
(AnnualCost / 12) * 1000000
END AS calcColRate
FROM
Rate
表中没有别名。
从我可以收集到的内容,可以简化为:
SELECT
*,
(ISNULL(AnnualCost,0)/12) * 1000000
from
Rate
或者,正如Jabs所指出的那样......
AnnualCost
另外注意,根据INTEGER
的数据类型,您可能需要考虑除以小数,这样您就不会进行(AnnualCost / 12.0) * 1000000.0
除法并成为精度丢失的牺牲品。
select
(1 / 12) * 1000000 --Returns 0
,(1 / 12.0) * 1000000 --Returns 83333.000000
示例强>
.flex-grid {
background: #f00;
display: grid;
grid-template-columns: auto 512px 512px auto;
grid-template-areas:
"space1 left right space2";
}
.flex-child {
text-align:center;
}
.space1, #left {
background: #0f0;
}
.space2, #right {
background: #00f;
}
.space1 {
grid-area: space1;
}
.space2 {
grid-area: space2;
}
#left {
grid-area: left;
}
#right {
grid-area: right;
}
将来,如果您的代码有效并且您只是在寻找改进,我会将其发布在Code Review上,因为它更适合此类请求。
答案 1 :(得分:2)
您的问题中似乎缺少一些重要信息。如果您想要的所有想要的是FinalCalcColRate
表格中每一行的Rates
,那么您可以像@scsimon在他/她的回答中所做的那样执行一步:
select
r.*,
FinalCalcColRate = case when r.AnnualCost is null then 0 else r.AnnualCost / 12 * 100000 end
from
dbo.Rates r;
或者在SQL Server中使用coalesce
(或isnull
)的类似实现;有关差异的详细信息,请参阅this question:
select
r.*,
FinalCalcColRate = coalesce(r.AnnualCost / 12 * 100000, 0)
from
dbo.Rates r;
然而,@ scsimon的查询与原始查询之间的一个区别是前者仅输出最终计算值,而后者也产生所有中间值。从您的问题中不清楚此查询的消费者是否需要这些值。如果他们愿意,那么你可以简单地包括它们:
select
r.*,
CalcColRate = coalesce(r.AnnualCost / 12, 0),
NewCalcColRate = coalesce(r.AnnualCost / 12 * 100, 0),
FinalCalcColRate = coalesce(r.AnnualCost / 12 * 100000, 0)
from
dbo.Rates r;
这里有一些重复的逻辑 - 例如,如果您要更改CalcColRate
的定义,您还必须手动更改NewCalcColRate
和FinalCalcColRate
的表达式 - 但它足够小,我怀疑它值得担心。尽管如此,如果原始查询中的构造是出于避免这种重复的愿望,那么您可以重构查询以使用CTE而不是嵌套查询:
with CalcCTE as
(
select
r.*,
CalcColRate = coalesce(r.AnnualCost / 12, 0)
from
dbo.Rates r
),
NewCalcColCTE as
(
select
c.*,
NewCalcColRate = c.CalcColRate * 100
from
CalcCTE c
)
select
n.*,
FinalCalcColRate = n.NewCalcColRate * 1000
from
NewCalcColCTE n;
这显然比我之前独立定义所有值的查询更长,更难以理解,但它确实具有以下优点:每个步骤都是在最后一步构建的,并且CTE公式往往更具可读性比同等的嵌套查询集合,因为步骤是按照它们被评估的顺序编写的,而对于嵌套查询,你必须找到最里面的点并向外工作,这可能会让人感到困惑。