【发布时间】:2016-04-14 20:53:55
【问题描述】:
我已经编写了下面的查询,它可以正常工作并产生正确的结果。但是我觉得这可能不是很有效,因为我的 SQL 经验非常有限。
突出的主要是我计算名义差异和价格差异的地方,这两行。
1. isnull(hld.Nominal, 0) - isnull(nav.Nominal, 0) NomDiff
2. isnull((hld.Price / nav.LocalPrice - 1) * 100, 0)
因为我还必须将这两行都放在 where 条件中,所以相同的计算要计算两次。编写此查询的更好方法是什么?
;WITH hld AS
(
SELECT id,
name,
Nominal,
Price
FROM tblIH
),
nav AS
(
SELECT id,
name,
Nominal,
LocalPrice
FROM tblNC
)
SELECT COALESCE(hld.id, nav.id) id,
COALESCE(nav.name, hld.name) name,
ISNULL(hld.Nominal, 0) HldNom,
ISNULL(nav.Nominal, 0) NavNom,
ISNULL(hld.Nominal, 0) - ISNULL(nav.Nominal, 0) NomDiff,
ISNULL(hld.Price, 0) HldPrice,
ISNULL(nav.LocalPrice, 0) NavPrice,
ISNULL((hld.Price / nav.LocalPrice - 1) * 100, 0)
FROM hld
FULL OUTER JOIN nav ON hld.id = nav.id
WHERE ISNULL(hld.Nominal, 0) - ISNULL(nav.Nominal, 0) <> 0
OR ISNULL((hld.Price / nav.LocalPrice - 1) * 100, 0) <> 0
【问题讨论】:
-
我建议您提供示例数据、期望的结果以及您想要做什么的说明。
-
你可以使用 COALESCE 而不是 ISNULL 但你可能会有相同的性能。 COALESCE 有时会稍微好一些,并且由于您多次调用 INSULL,您可以获得一些性能
-
计算部分可以包含在第二个 CTE 中,然后您可以在最终选择查询中简单地选择或过滤计算字段作为列名,而无需进一步计算。
-
@Antonio:在大多数情况下,ISNULL 和 COALESCE 是相同的。见dba.stackexchange.com/a/4277/630
-
@gbn 不完全正确。正如我所说的“他们可能会有相同的表现”。这可能取决于他使用的 SQL 服务器版本。 AFAIK 在某些情况下,COALESCE 比 isnull 稍微好一点……而且他多次调用 ISNULL,他应该比较它们的用法。在我看来,这并没有那么困难和值得做的工作......见:mssqltips.com/tipImages2/2689_Coalesce_IsNull_Perf.png
标签: sql sql-server sql-server-2012