我从表中的第一个查询大约需要40秒,并创建超过80,000行。我想通过Site,Sequence,Total和任何操作系统版本来获取Windows 7应用程序的数量。
这些子查询有效,但当然它们会大大减慢这个过程。运行需要3.5小时。
有更有效的方法吗?
输出:
SoftwareName Sequence Site Win7/site Win7Installs/seq TotWin7apps TotalInstalls
Adobe Acrobat 1 BKN 1 5 626 7854
AutoCAD LT 1 BKN 1 1 3 15
Adobe Acrobat 1 CTW 4 5 626 7854
Adobe Captivate 1 CTW 1 1 8 60
查询:
WITH PCapps AS (
SELECT DISTINCT
Computer,
Sequence,
Site,
SoftwareName,
OS
FROM table
)
SELECT DISTINCT
SoftwareName,
Sequence,
Site,
(SELECT COUNT(p1.SoftwareName) FROM PCapps p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Site = pc.Site) as 'Win7/site',
(SELECT COUNT(p1.SoftwareName) FROM PCapps p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Sequence = pc.Sequence) as 'Win7Installs/seq',
(SELECT COUNT(p2.SoftwareName) FROM PCapps p2 WHERE p2.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise') as TotWin7apps,
(SELECT COUNT(p3.SoftwareName) FROM PCapps p3 WHERE p3.SoftwareName = pc.SoftwareName) as TotalInstalls
FROM PCapps pc
**更新:
使用@Jason Carter的提示,我创建了几个#temp表并加入它们。结果在不到一分钟的时间内运行得非常快(不比初始查询长很多)。这个方法与@ JasonCarter的解决方案略有不同,因为我按照他的初始提示创建了#temp表。我创建了几个#temp表,每个表都包含COUNT()s。
SELECT DISTINCT
Computer,
Sequence,
Site,
SoftwareName,
OS
INTO #PCapps
FROM TABLE
SELECT
SoftwareName,
Site,
COUNT(SoftwareName) AS [SiteInstalls]
INTO #SiteInstalls
FROM #PCapps
WHERE OS = 'Windows 7 Enterprise'
GROUP BY Site, SoftwareName
SELECT
SoftwareName,
Sequence,
COUNT(SoftwareName) AS [SeqInstalls]
INTO #SeqInstalls
FROM #PCapps
WHERE OS = 'Windows 7 Enterprise'
GROUP BY Sequence, SoftwareName
SELECT
SoftwareName,
COUNT(SoftwareName) AS [Win7Installs]
INTO #Win7Installs
FROM #PCapps
WHERE OS = 'Windows 7 Enterprise'
GROUP BY SoftwareName
SELECT
SoftwareName,
COUNT(SoftwareName) AS [AppInstalls]
INTO #AppInstalls
FROM #PCapps
GROUP BY SoftwareName
SELECT
pc.SoftwareName,
pc.Sequence,
pc.Site,
sit7.SiteInstalls,
seq7.SeqInstalls,
w7.Win7Installs,
ai.AppInstalls
FROM #PCapps pc
LEFT OUTER JOIN #SiteInstalls sit7 ON sit7.SoftwareName = pc.SoftwareName AND sit7.Site = pc.Site
LEFT OUTER JOIN #SeqInstalls seq7 ON seq7.SoftwareName = pc.SoftwareName AND seq7.Sequence = pc.Sequence
LEFT OUTER JOIN #Win7Installs w7 ON w7.SoftwareName = pc.SoftwareName
LEFT OUTER JOIN #AppInstalls ai ON ai.Softwarename = pc.SoftwareName
DROP TABLE #PCapps
DROP TABLE #SiteInstalls
DROP TABLE #SeqInstalls
DROP TABLE #Win7Installs
DROP TABLE #AppInstalls
答案 0 :(得分:1)
我会先尝试将子查询运行到临时表中以收集计数,然后提取总计数。通过查询设置的方式,它将为每个PCapps行运行每个子查询一次,这就是为什么它需要这么长时间。
尝试这样的事情:
declare @t table (Computer varchar(10), Sequence int, Site varchar(3), SoftwareName varchar(20), OS varchar(20) )
insert into @t values
('C1',1,'BKN','Adobe Acrobat','Win7')
,('C2',1,'BKN','Adobe Acrobat','Win7')
,('C3',1,'BKN','Adobe Acrobat','Win7')
,('C1',1,'BKN','AutoCAD LT ','Win7')
,('C3',1,'BKN','AutoCAD LT ','Win7')
,('B1',2,'CTW','Adobe Acrobat','Win7')
,('B2',2,'CTW','Adobe Acrobat','Win7')
,('B3',3,'CTW','Adobe LT','Win7')
,('B4',3,'CTW','Adobe Acrobat','Win7')
,('A1',2,'CTW','Adobe Acrobat','Win7')
,('A2',2,'CTW','Adobe LT','Win7')
,('A3',2,'CTW','Adobe Acrobat','Win7')
,('X4',3,'CTW','Adobe Acrobat','WinXP')
,('X1',2,'CTW','Adobe Acrobat','WinXP')
,('X2',2,'CTW','Adobe LT','WinXP')
,('X3',2,'CTW','Adobe Acrobat','WinXP')
,('A4',2,'CTW','Adobe Acrobat','Win7');
SELECT
Site,
OS,
SoftwareName,
Sequence,
COUNT(SoftwareName) as 'Count'
into #SiteSpecific
FROM @t
group by Site, OS, SoftwareName, Sequence;
WITH PCapps AS (
SELECT DISTINCT
Computer,
Sequence,
Site,
SoftwareName,
OS
FROM @t
)
SELECT
DISTINCT
PC.SoftwareName,
PC.Sequence,
PC.Site,
PerSeq.[Count] as 'Win7Installs/seq',
PerSite.[Count] as TotWin7apps,
total.[Count] as TotalInstalls
FROM PCapps pc
inner join (select SoftwareName, Sequence, OS, sum([Count]) [Count] from #SiteSpecific group by SoftwareName, Sequence, OS) PerSeq
on PerSeq.SoftwareName = pc.Softwarename
AND PerSeq.Sequence = pc.Sequence
AND PerSeq.OS = pc.OS
inner join (select SoftwareName, Site, OS, sum([Count]) [Count] from #SiteSpecific group by SoftwareName, Site, OS) PerSite
on PerSite.SoftwareName = pc.Softwarename
AND PerSite.Site = pc.Site
AND PerSite.OS = pc.OS
inner join (select SoftwareName, sum([Count]) [Count] from #SiteSpecific group by SoftwareName) Total
on Total.SoftwareName = pc.Softwarename
where Pc.OS='Win7'
order by SoftwareName, Sequence, Site
答案 1 :(得分:0)
对我来说真的很奇怪......优化器利用并行性来使子查询非常高效。我填写了一个有120K记录的虚拟表,并尝试了下面的内容。第三个查询只比第一个查询(你的)略高一些,但代价是更复杂。我会原样离开你的。可能有一个更好的解决方案,但你的看起来不错。你需要多长时间来处理80K行?
WITH PCapps2 AS (
SELECT DISTINCT
Computer,
Sequence,
Site,
SoftwareName,
OS
FROM pcapps
)
SELECT DISTINCT
SoftwareName,
Sequence,
Site,
(SELECT COUNT(p1.SoftwareName) FROM PCapps2 p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Site = pc.Site) as 'Win7/site',
(SELECT COUNT(p1.SoftwareName) FROM PCapps2 p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Sequence = pc.Sequence) as 'Win7Installs/seq',
(SELECT COUNT(p2.SoftwareName) FROM PCapps2 p2 WHERE p2.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise') as TotWin7apps,
(SELECT COUNT(p3.SoftwareName) FROM PCapps2 p3 WHERE p3.SoftwareName = pc.SoftwareName) as TotalInstalls
FROM PCapps2 pc
;WITH PCapps2 AS (
SELECT DISTINCT
Computer,
Sequence,
Site,
SoftwareName,
OS
FROM pcapps
)
SELECT DISTINCT
SoftwareName,
Sequence,
Site,
COUNT(case when os = 'Windows 7 Enterprise' then 1 end) over (partition by pc.Softwarename,pc.Site) as 'Win7/site',
COUNT(case when os = 'Windows 7 Enterprise' then 1 end) over (partition by pc.Softwarename,pc.Sequence) as 'Win7Installs/seq',
COUNT(case when os = 'Windows 7 Enterprise' then 1 end) over (partition by pc.Softwarename) as TotWin7apps,
COUNT(*) over (partition by pc.Softwarename) as TotalInstalls
FROM PCapps2 pc
;WITH PCapps2 AS (
SELECT DISTINCT
Computer,
Sequence,
Site,
SoftwareName,
OS
FROM pcapps
), a as (
select softwarename, site, COUNT(*) as 'Win7/site'
from pcapps2
where os = 'Windows 7 Enterprise'
group by softwarename, site
), b as (
select softwarename, sequence, COUNT(*) as 'Win7Installs/seq'
from pcapps2
where os = 'Windows 7 Enterprise'
group by softwarename, sequence
), c as (
select softwarename, COUNT(case when os = 'Windows 7 Enterprise' then 1 end) as TotWin7apps, COUNT(*) as TotalInstalls
from pcapps2
group by softwarename
), d as (
select distinct softwarename, sequence, site
from pcapps2
)
select d.*, isnull(a.[Win7/site], 0) as [Win7/site], isnull(b.[Win7Installs/seq],0) as [Win7Installs/seq]
, isnull(c.TotWin7apps,0) as TotWin7apps, isnull(c.TotalInstalls, 0) as TotalInstalls
from d
left join a on d.softwarename = a.softwarename and d.site = a.site
left join b on d.softwarename = b.softwarename and d.sequence = b.sequence
left join c on d.softwarename = c.softwarename
首先查询: 表'pcapps'。扫描计数15,逻辑读取6630,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。 表'工作台'。扫描计数0,逻辑读取0,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
第二个查询: 表'pcapps'。扫描计数3,逻辑读取1326,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。 表'工作台'。扫描计数18,逻辑读取1983591,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
第三个查询: 表'pcapps'。扫描计数12,逻辑读取5304,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读取读取0。 表'工作台'。扫描计数0,逻辑读取0,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。