我有一个选择查询,它有很多连接,它有5个内部查询。
使用嵌套查询时,它看起来像
Query(NestedQuery1(NestedQuery2(NestedQuery3(NestedQuery4(NestedQuery5)as C)as M)as X)as D)
它变得非常混乱......
另一方面,我可以像
那样做NestedQuery5 INTO #C
NestedQuery4 INTO #M From #C
.
.
.
Query From D
我的问题是你会使用嵌套或使用临时表的哪一个?两者都不是一个选项
p.s我是一个不到一周的SQL经验的菜鸟,但无论我使用第一种方法还是第二种方法,查询都能正常工作。
/*set period*/
DECLARE @DATE1 DATETIME
SET @DATE1 ='01.01.2000'
DECLARE @DATE2 DATETIME
SET @DATE2 = '01.01.2050'
SELECT contactid,
country,
city,
itemsbought,
lastlogindate,
email,
lastbuydate,
openscount,
clickscount,
newslettersrecived,
averagereadtime,
lastnewsletterdate,
menge 'BuyCount',
( Rank()
OVER (
ORDER BY menge DESC) ) mengeRank,
ekavg 'EKØ',
( Rank()
OVER (
ORDER BY ekavg DESC) ) ekavgRank,
ekt 'EKTotal',
( Rank()
OVER (
ORDER BY ekt DESC) ) ektRank,
vkavg 'VKØ',
( Rank()
OVER (
ORDER BY vkavg DESC) ) vkavgRank,
vkt 'VKTotal',
( Rank()
OVER (
ORDER BY vkt DESC) ) vktRank,
XS.margent / XS.menge 'MargenØ',
( Rank()
OVER (
ORDER BY XS.margent / XS.menge DESC) ) MarginAVGRank,
margent 'MargenTotal',
( Rank()
OVER (
ORDER BY margent DESC) ) margentotalRank,
CASE
WHEN Isnull(vkt, 0) != 0
AND Isnull(menge, 0) > 1 THEN ( ( vkt - ekt ) / vkt ) * 100
ELSE 0
END AS 'Margen%'
FROM (SELECT RR.*,
CASE
WHEN Isnull(menge, 0) != 0 THEN ekt / menge
ELSE NULL
END AS EKAVG,
vkt - ekt MargenT,
CASE
WHEN Isnull(menge, 0) != 0 THEN vkt / menge
ELSE NULL
END AS VKAVG
FROM (SELECT Max(orderdate) lastbuydate,
itemsbought,
contactid,
country,
city,
email,
lastlogindate,
Sum(menge) Menge,
Sum(ek) EKT,
Sum(vk) VKT
FROM (SELECT AA.*,
menge * Isnull(ekprice, 0)
AS EK,
( Isnull(unitprice, 0) / producttotal ) *
Isnull(otax, 0)
otaxamount,
( Isnull(unitprice, 0) / producttotal ) * Isnull(
odiscount, 0)
discountamount,
( Isnull(unitprice, 0) / producttotal ) *
Isnull(coupondiscount, 0)
coupondiscountamount,
menge * ( Isnull(unitprice, 0) - (
Isnull(unitprice, 0) / producttotal )
*
Isnull(otax, 0)
- ( Isnull(unitprice, 0) / producttotal
) *
Isnull(odiscount, 0) -
(
Isnull(
unitprice, 0) / producttotal )
*
Isnull(
coupondiscount
, 0)
)
AS VK
FROM (SELECT i.catalogid,
c.contactid,
c.city,
c.country,
c.firstname,
c.lastname,
c.email,
c.lastlogindate,
i.supplierid,
p.cname,
i.ekprice,
i.unitprice,
o.odate,
o.otax,
o.odiscount,
o.oshipcost,
o.coupondiscount,
o.producttotal,
s.name,
Stuff((SELECT
','
+ COALESCE(Ltrim(Rtrim(i.catalogid)), '')
FROM orders o
INNER JOIN oitems i
ON o.orderid =
i.orderid
WHERE o.ocustomerid = c.contactid
FOR xml path('')), 1, 1, '') AS
ItemsBought,
CASE WHEN o.oshippeddate BETWEEN @Date1
AND
@Date2 THEN
Isnull(i.f2, 0)
ELSE 0
END + CASE WHEN o.oshippeddate2 BETWEEN
@Date1
AND
@Date2 THEN
Isnull(i.f3, 0)
ELSE 0 END + CASE WHEN o.oshippeddate3
BETWEEN
@Date1
AND @Date2
THEN
Isnull(i.f4, 0) ELSE 0 END AS
Menge,
CASE
WHEN o.oshippeddate IS NOT NULL
OR o.oshippeddate2 IS NOT NULL
OR o.oshippeddate3 IS NOT NULL
THEN
odate
ELSE NULL
END AS
orderdate
FROM orders o
INNER JOIN oitems i
ON i.orderid = o.orderid
LEFT OUTER JOIN products p
ON i.catalogid = p.catalogid
LEFT OUTER JOIN suppliers s
ON
i.supplierid = s.supplierid
RIGHT OUTER JOIN customers c
ON
o.ocustomerid = c.contactid)AS
AA) T
GROUP BY T.contactid,
T.email,
T.itemsbought,
T.country,
T.lastlogindate,
T.city) AS RR
GROUP BY RR.ekt,
RR.menge,
RR.vkt,
RR.country,
RR.lastlogindate,
RR.contactid,
RR.itemsbought,
RR.city,
RR.email,
RR.lastbuydate) XS
INNER JOIN customerstatistics cst
ON XS.contactid = cst.id
ORDER BY buycount
答案 0 :(得分:1)
我承认:你并没有过于复杂化。您寻求的统计数据确实需要这么多级别的(子)查询。
当然,如果您将中间值存储在事务表或其他余额表中,查询将变得更加简单,但这意味着您将不得不维护冗余数据,这可能是令人讨厌的。您是否发现附加列和/或表格的可接受程度也是一种品味问题。
关于功能的一点评论。我对统计数据知之甚少,但对我来说,按数字范围而不是精确数量对结果进行排名似乎更合乎逻辑;最微小的差异可能已经导致两个几乎相等的销售额不计入排名。
从技术上讲,查询对我来说非常好。我注意到在最里面的查询(AA)中,您正在检索的数据比您当时真正需要的数据多。
在最里面的查询中加入供应商和客户只有一个好处:您可以在另一个上下文中重复使用完全相同的查询来检索销售订单详细信息。在较大的查询由较小的查询自动组成的环境中可能很有用。如果全部是手工劳动,那么您也可以删除供应商加入并将客户加入到外部。它会略微提高可读性和性能(尽管你已经指出这目前不是问题)。
至于你原来的问题(嵌套子查询与临时表),我认为它不会产生太大的影响。理论上,嵌套子查询是最好的;让查询优化器决定什么是最佳策略。
总而言之,我认为你做得很好。