我有以下查询, 此查询多次使用select子句中的子查询
SELECT DISTINCT CAST(decCostFactor as decimal(9,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText,12,4)
我想删除此子查询。我尝试使用group by CAST(decCostFactor as decimal(9,4)),但现在它要求在cluase中包含其他列。
非常感谢任何帮助。
主要查询是
DECLARE @Region int=10006
SELECT
st.strRegion,
st.intStore,
st.strStoreName,
tblSticker.intStickerNo ,
tblSticker.strTeamNo AS strTeam ,
tblSticker.dtmFixtureStartDate AS dtmStartDate ,
tblSticker.intAreaNo ,
SUBSTRING ( tblSticker.strMiscText , 8 , 30 ) AS strSection ,
tblDetail.intLineNum ,
tblDetail.strBarcode ,
tblDetail.intBarcodeLength ,
tblDetail.intBarcodeType ,
tblDetail.strBarcodeEntrySw AS strKeyBarcode ,
tblDetail.fltPrice AS fltPrice ,
tblDetail.fltQty AS fltQty ,
tblDetail.strPTCCode4 AS strKeyPrice ,
tblDetail.strPTCCode5 AS strKeyQty ,
SUBSTRING ( tblDetail.strMiscText , 1 , 1 ) AS strNOF ,
SUBSTRING ( tblDetail.strClientText , 1 , 30 ) AS strDesc ,
SUBSTRING ( tblDetail.strMiscText , 12 , 4 ) AS strSubTeam ,
SUBSTRING ( tblDetail.strMiscText , 16 , 25 ) AS strSubTeamDesc ,
SUBSTRING ( tblDetail.strClientText , 34 , 3 ) AS strSubDept ,
SUBSTRING ( tblDetail.strClientText , 37 , 3 ) AS strClass ,
SUBSTRING ( tblDetail.strClientText , 40 , 3 ) AS strSubClass ,
SUBSTRING ( tblDetail.strMiscText , 41 , 7 ) AS strCostFactor ,
SUBSTRING ( tblDetail.strMiscText , 41 , 1 ) AS strPerishableFlag ,
tblSubTeam.blnBreakoutCost,
fltPriceLb = tblDetail.fltClientMisc1,
fltCostLb = CASE
WHEN tblDetail.decCost > 0
THEN tblDetail.decCost
ELSE tblDetail.fltClientMisc1 *
( SELECT DISTINCT CAST(decCostFactor as decimal(6,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText,12,4)
)
END,
strVendor = CASE WHEN tblDetail.strVendor IS NULL THEN 'NA' ELSE tblDetail.strVendor END,
fltWeightSouth = CASE
WHEN tblDetail.fltClientMisc1 > 0
THEN (tblDetail.fltPrice / tblDetail.fltClientMisc1)
WHEN SUBSTRING(tblDetail.strMiscText,49,1) <> 'R'
AND tblDetail.fltClientMisc1 = 0
THEN cast(SUBSTRING(tblDetail.strClientText,43,6) as float)
ELSE 0
END,
fltCostSouth = ISNULL(CASE
WHEN SUBSTRING(tblDetail.strMiscText,50,1) = 'C'
THEN (tblDetail.fltPrice )
ELSE
-- To calculate cost for Subteam 3100 in the south region - Thomas - 2/19/2008
CASE
WHEN (SUBSTRING(tblDetail.strMiscText,12,4) = '3100')
AND (Substring(tblDetail.strMiscText,1,1) <> 'N')
THEN fltprice *
( SELECT DISTINCT CAST(decCostFactor as decimal(6,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText, 12, 4)
)
ELSE CASE
WHEN tblDetail.fltClientMisc1 > 0 and tblDetail.decCost > 0
-- modified by TA to remedy Extended Retail for weighted items
THEN (tblDetail.fltPrice / tblDetail.fltClientMisc1) * tblDetail.decCost
ELSE CASE
WHEN (Substring(tblDetail.strMiscText,1,1) = 'N')
Or (tblDetail.strBarcode = '00000000000000')
THEN CASE
WHEN (fltprice = 0 and tblDetail.decCost > 0)
THEN CASE
WHEN SUBSTRING(tblDetail.strClientText,43,6) <> ''
THEN CASE
WHEN CAST(SUBSTRING(tblDetail.strClientText,43,6) as float) > 0
THEN CAST(SUBSTRING(tblDetail.strClientText,43,6) as float)*tblDetail.decCost
ELSE fltTotalUnits*tblDetail.decCost
END
ELSE 0 * tblDetail.decCost
END
ELSE CASE
WHEN (Substring(tblDetail.strMiscText,41,7)) = ''
THEN fltprice * 0
ELSE fltprice * Cast(Substring(tblDetail.strMiscText,41,7) as decimal(6,4))
END
END
ELSE CASE
WHEN (fltprice > 0 and tblDetail.decCost = 0)
THEN fltprice *
( SELECT DISTINCT CAST(decCostFactor as decimal(6,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText,12,4)
)
ELSE CASE
WHEN (fltprice = 0 and tblDetail.decCost > 0)
THEN CASE
WHEN CAST(SUBSTRING(tblDetail.strClientText,43,6) as float) > 0
THEN CAST(SUBSTRING(tblDetail.strClientText,43,6) as float) * tblDetail.decCost
ELSE tblDetail.decCost
END
ELSE tblDetail.decCost
END
END
END
END
END
END,0),
fltItemCost = ISNULL(CASE
WHEN ((((Substring(tblDetail.strMiscText,41,7) = '00.0000')
or (tblDetail.fltClientMisc1 = 0))
or (tblDetail.decCost = 0))
and Substring(tblDetail.strMiscText,1,1) <> 'N')
THEN CASE
WHEN (fltprice > 0 and tblDetail.decCost = 0)
THEN fltprice *
( SELECT DISTINCT CAST(decCostFactor as decimal(9,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText,12,4)
)
ELSE CASE
WHEN (fltprice = 0 and tblDetail.decCost > 0)
THEN tblDetail.decCost
ELSE CASE
WHEN (Substring(tblDetail.strMiscText,41,7)) = ''
THEN fltprice * 0
ELSE fltprice * Cast(Substring(tblDetail.strMiscText,41,7) as decimal(9,4))
END
END
END
ELSE CASE
WHEN (Substring(tblDetail.strMiscText,1,1) = 'N')
Or (tblDetail.strBarcode = '00000000000000')
THEN fltprice * Cast(Substring(tblDetail.strMiscText,41,7) as decimal(9,4))
ELSE CASE
WHEN (fltprice > 0 and tblDetail.decCost = 0)
THEN fltprice *
( SELECT DISTINCT CAST(decCostFactor as decimal(9,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText,12,4)
)
ELSE CASE
WHEN (Substring(tblDetail.strMiscText,41,7)) = ''
THEN fltprice * 0
ELSE fltprice * Cast(Substring(tblDetail.strMiscText,41,7) as decimal(9,4))
END
END
END
END, 0),
strWeight = SUBSTRING(tblDetail.strClientText, 43, 6)
FROM
tblSticker WITH ( NOLOCK )
INNER JOIN tblDetail WITH ( NOLOCK )
ON tblSticker.intStore = tblDetail.intStore
AND tblSticker.intStickerNo = tblDetail.intStickerNo
AND tblSticker.dtmStickerDate = tblDetail.dtmStickerDate
LEFT OUTER JOIN tblsubteam
ON tblDetail.intStore = tblSubTeam.intStore
AND SUBSTRING ( tblDetail.strMiscText , 12 , 4 ) = tblSubTeam.strSubTeam
inner join tblStore st on st.intStore=tblDetail.intStore
--fix add join to store. Kevin 2/8/07
-- AND SUBSTRING ( tblDetail.strMiscText , 12 , 4 ) = tblSubTeam.strSubTeam
--fix fix move join to store outside of compound conditional. Eddie 9/2/11
WHERE
((@Region is not null and st.intRegion=@Region) or @Region is null)
AND st.intStore < 90000
AND ( tblSticker.intStickerNo NOT BETWEEN 334717100
AND 334717299 )
AND tblSticker.strRescanSW = 'N'
AND ( tblSticker.strEmptyStatus = ' '
OR tblSticker.strEmptyStatus = '*' )
ORDER BY st.strStoreName,
tblSticker.intStickerNo ,
tblDetail.intLineNum
答案 0 :(得分:4)
您可以将查询移至APPLY,这可确保只执行一次。
我认为你的例子会变成:
FROM tblSticker WITH ( NOLOCK )
INNER JOIN tblDetail WITH ( NOLOCK )
ON tblSticker.intStore = tblDetail.intStore
AND tblSticker.intStickerNo = tblDetail.intStickerNo
AND tblSticker.dtmStickerDate = tblDetail.dtmStickerDate
LEFT OUTER JOIN tblsubteam
ON tblDetail.intStore = tblSubTeam.intStore
AND SUBSTRING ( tblDetail.strMiscText , 12 , 4 ) = tblSubTeam.strSubTeam
INNER JOIN tblStore st
ON st.intStore=tblDetail.intStore
OUTER APPLY
( SELECT DeCostFactor = CAST(decCostFactor AS DECIMAL(9,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText,12,4)
) dcf
然后,您可以简单地引用dcf.DeCostFactor
。
作为一般测试,我使用了以下内容,与单个APPLY相比,它只执行相关子查询4次
SET STATISTICS IO ON;
WITH T AS
( SELECT A = Number, B = Number + 1
FROM Master..spt_values
WHERE Type = 'P'
)
SELECT T.A,
T.B,
SubQuery = (SELECT T2.B FROM T T2 WHERE T2.A = T.B),
SubQuery2 = (SELECT T2.B FROM T T2 WHERE T2.A = T.B),
SubQuery3 = (SELECT T2.B FROM T T2 WHERE T2.A = T.B),
SubQuery4 = (SELECT T2.B FROM T T2 WHERE T2.A = T.B)
FROM T;
-- USING OUTER APPLY
WITH T AS
( SELECT A = Number, B = Number + 1
FROM Master..spt_values
WHERE Type = 'P'
)
SELECT T.A,
T.B,
SubQuery = SubQuery.B,
SubQuery2 = SubQuery.B,
SubQuery3 = SubQuery.B,
SubQuery4 = SubQuery.B
FROM T
OUTER APPLY
( SELECT T2.B
FROM T T2
WHERE T2.A = T.B
) SubQuery;
IO统计数据不言自明:
多个子查询
Table 'spt_values'. Scan count 8193, logical reads 24625, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
外部申请
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'spt_values'. Scan count 2, logical reads 18, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
修改强>
我认为你根本不需要子查询,你已经按照相同的标准加入了表tblSubteam
:
LEFT OUTER JOIN tblsubteam
ON tblDetail.intStore = tblSubTeam.intStore
AND SUBSTRING ( tblDetail.strMiscText , 12 , 4 ) = tblSubTeam.strSubTeam
为什么不能只使用tblsubteam.DeCostFactor
而不是子查询?
答案 1 :(得分:1)
您将此作为select
子句中的子查询。因此,它必须返回一个值。因此,您可以将其替换为:
( SELECT top 1 CAST(decCostFactor as decimal(6,4))
FROM tblsubteam WITH (NOLOCK)
WHERE intstore = st.intStore
AND strsubteam = SUBSTRING(tblDetail.strMiscText,12,4)
)
SQL Server非常适合优化。但是,distinct
可能会造成问题。删除distinct并且只取任意值可能会改善优化。
但是,检查的方法是查看执行计划。
通过在tblsubteam(instore, strsubteam, decCostFactor)
上建立索引,可能会提高效果。