回答

收藏

使用派生表查询的优点是什么?

技术问答 技术问答 226 人阅读 | 0 人回复 | 2023-09-14

我知道如何使用衍生表,但我仍然可以看到任何使用它们的真正优势。; m5 U! n5 c3 D# B) @, [
例如,下面的文章http://techahead.wordpress.com/2007/10/01/sql-derived-
# ?4 t3 f$ Z9 E9 p6 V8 R  ]tables/在中间,作者试图显示使用衍生表的查询优于没有例子的查询。我们需要生成一份报告,以显示1996年每个客户下的订单总数。我们希望结果集包括所有客户,包括当年没有下订单的客户和从未下订单的客户(他使用)Northwind数据库)。, u+ b& y# }! C/ a' e$ x% \0 b% C
然而,当我比较这两个查询时,我看不到使用衍生表查询的任何优点(如果没有其他问题,使用衍生表似乎不会简化我们的代码,至少在这个例子中):
% ^% ]) ~' u  q! a! J) F/ Q常规查询:
0 I7 Y7 P- y( B& ASELECT C.CustomerID,C.CompanyName,COUNT(O.OrderID) AS TotalOrdersFROM Customers C LEFT OUTER JOIN Orders O ON       C.CustomerID = O.CustomerID AND YEAR(O.OrderDate) = 1996GROUP BY C.CustomerID,C.CompanyName使用派生表查询:& F6 @7 [$ e: a3 [
SELECT C.CustomerID,C.CompanyName,COUNT(dOrders.OrderID) AS TotalOrdersFROM Customers C LEFT OUTER JOIN        (SELECT * FROM Orders WHERE YEAR(Orders.OrderDate) = 1996) AS dOrders     ON        C.CustomerID = dOrders.CustomerIDGROUP BY C.CustomerID,C.CompanyName也许这不是一个好例子,所以你能给我看一个例子,衍生表的好处更明显吗?+ X# ?8 q9 F, f/ s4 I2 w7 d
谢谢
+ e1 z' t( T5 x# C. d8 q回复GBN:
1 {2 x7 [: w8 _$ U/ m3 D在这种情况下,如果客户与产品无关,则无法同时捕获产品和订单汇总。
  A! E% H" C6 x/ L: ^
你能详细说明你的意思吗?以下查询不会产生与您查询相同的结果集:+ p0 _: S, G5 a8 O; G' ]. U
SELECT      C.CustomerID,C.CompanyName,    COUNT(O.OrderID) AS TotalOrders,    COUNT(DISTINCT P.ProductID) AS DifferentProducts FROM Customers C LEFT OUTER JOIN Orders O ON       C.CustomerID = O.CustomerID AND YEAR(O.OrderDate) = 1996   LEFT OUTER JOIN Products P ON        O.somethingID = P.somethingID  GROUP BY C.CustomerID,C.CompanyName回复到CADE ROUX:+ V) t+ G: s# k
此外,如果使用大量共享中间计算的表达式衍生列,则只有一组嵌套式衍生表或堆叠式衍生列CTE唯一的办法就是这样做:
+ ~. {4 O  V: ?# y3 W
SELECT x,y,z1,z2FROM (    SELECT *  x   y AS z1  x - y AS z2    FROM (        SELECT x * 2 AS y        FROM A   ) AS A) AS A以下查询不会产生与上述查询相同的结果:" c2 E* T5 s, M3 L
SELECT x,x * 2 AS y,x   x*2 AS z1,x - x*2 AS z2FROM A                / F! @" T3 H, g8 c7 {
    解决方案:                                                                $ i% ^- T6 S8 C! U" n6 G
                                                                在你的例子中,衍生表并不是严格必要的。在许多情况下,你可能需要加入一个聚合物或类似的聚合物,而衍生物实际上是处理这个问题的唯一方法:9 E3 u3 K4 u9 k( Q4 L6 b/ D
SELECT *FROM ALEFT JOIN  SELECT x,SUM(y)    FROM B    GROUP BY x) AS B    ON B.x = A.x此外,如果使用大量共享中间计算的表达式衍生列,则只有一组嵌套式衍生表或堆叠式衍生列CTE唯一的办法就是这样做:
' k3 [5 J4 ~& A+ P! ~SELECT x,y,z1,z2FROM  SELECT *  x   y AS z1  x - y AS z2    FROM      SELECT x * 2 AS y        FROM A   ) AS A) AS A就可维护性而言,使用堆叠CTE或者衍生表(它们基本上是等效的)可以使代码更可读和可维护,并便于剪切和粘贴的重用和重化器通常很容易变平。$ i1 W# P' p9 A# c
我通常使用堆叠CTE而不是嵌套来提高可读性(两个例子相同):
* \  z2 t5 y4 ?0 a7 v+ c. `WITH B AS  SELECT x,SUM(y)    FROM B    GROUP BY x)SELECT *FROM ALEFT JOIN B    ON B.x = A.xWITH A1 AS  SELECT x * 2 AS y    FROM A),A2 AS  SELECT *  x   y AS z1  x - y AS z2    FROM A1)SELECT x,y,z1,z2FROM A2关于你的问题:
" l3 C0 g& C$ C0 h1 ]SELECT x,x * 2 AS y,x   x*2 AS z1,x - x*2 AS z2 FROM A这使x * 2代码重复3次。如果需要更改此业务规则,则必须在方更改-$ R& t  Z& c0 F+ g; Y* r# H
注入缺陷的方法。当你只需要在一个地方定义和一致的中间计算时,情况就会变得更加复杂。
. h1 o" J  g& i7 S( Q若能内联SQL8 o, M9 _3 K* q. E6 o( C* f2 I" H
Server标量用户定义函数(或者可以接受执行),这不是什么大问题,你可以简单地构建它UDF堆叠结果,优化器可以消除冗余调用。不幸的是,SQL
* A4 n7 e# c; u0 ^) F, c5 N3 S" ~! sServer的标量UDF大量行不能很好地处理。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则