【问题标题】:query with calculations most efficient way用计算最有效的方式查询
【发布时间】: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


【解决方案1】:

首先选择不带 where 条件的结果,然后将结果作为表 tmp,然后添加带有 NomDiff 和 PriceDiff 列的 where 条件

;WITH hld AS
(
    SELECT id,
           name,
           Nominal,
           Price
    FROM tblIH
),
nav AS
(
    SELECT id,
           name,
           Nominal,
           LocalPrice
    FROM tblNC
)
select * 
from (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) PriceDiff
    FROM hld
    FULL OUTER JOIN nav ON hld.id = nav.id) tmp
where NomDiff <> 0 or PriceDiff <> 0

【讨论】:

    【解决方案2】:

    您可以在第二个 CTE 中包含计算部分,然后您可以在最终选择查询中将计算字段简单地选择或过滤为普通列,而无需进一步计算。

    【讨论】:

      猜你喜欢
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 2011-04-06
      • 2014-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多