SQL中涉及分组和平均的复杂查询的逻辑
我有两张桌子。SQL中涉及分组和平均的复杂查询的逻辑,sql,sql-server,Sql,Sql Server,我有两张桌子。 以下是获得所需输出所需的步骤。我可以继续第三步。请帮助我,因为这有点复杂,我无法理解如何进一步进行 表1 Site Code FailFlag Comments ModifiedDate ModifiedBy ABT A01 F Dfasdf 10/11/2011 Anna ABT A01 F dsfsdf 15/12/2012 Mand ABT A01 Rds 30
以下是获得所需输出所需的步骤。我可以继续第三步。请帮助我,因为这有点复杂,我无法理解如何进一步进行 表1
Site Code FailFlag Comments ModifiedDate ModifiedBy
ABT A01 F Dfasdf 10/11/2011 Anna
ABT A01 F dsfsdf 15/12/2012 Mand
ABT A01 Rds 30/03/2011 Tim
ABT A01 GHDs 02/12/2012 Andy
ABT A02 F dfd 09/05/2012 Anna
ABT A02 sdada 11/02/2013 Kathy
ABT A02 Dfg 15/05/2011 Rob
AFL A02 F asda 13/02/2011 Dan
AFL A02 dsaa 24/12/2010 Ryan
TRG A01 sdasd 16/04/2010 Richard
TRG K05 jksdh 23/04/2012 Mark
KLD K05 F sd 18/05/2013 Jim
KLD K05 dsfsd 10/03/2012 James
KLD K05 sdsd 12/05/2011 Luther
KTY K05 F saq 09/09/2012 Ryan
KTY K05 asd 04/04/2010 Kathy
KMD C02 F nas 29/02/2012 Rob
KMD C02 asda 11/11/2011 Andy
表2:
Site Code Freq StartDate EndDate
ABT A01 43 01/01/2011 01/02/2012
ABT A02 254 01/01/2011 19/02/2011
ABT A02 109 20/02/2011 01/01/2012
ABT A02 12 02/01/2012 01/01/2013
AFL A02 13 01/01/2011 01/02/2012
TRG A01 122 01/01/2011 01/02/2012
TRG K05 61 01/01/2011 01/02/2012
KLD KO5 33 01/01/2011 15/05/2012
KLD K05 79 16/05/2012 01/01/2013
KTY K05 52 01/01/2011 01/02/2012
KMD C02 78 01/01/2011 01/02/2012
ZYT G01 11 01/01/2011 01/02/2012
PYN A01 15 01/01/2011 01/02/2012
DYN F08 122 01/01/2011 01/02/2012
步骤:
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN F = 'F' THEN 1 ELSE 0 END) FROM Table1
GROUP BY Site,Det
Site Code Count FailFlagCount
ABT A01 4 2
ABT A02 3 1
AFL A02 2 1
TRG A01 1 0
TRG K05 1 0
KLD KO5 3 1
KTY K05 2 1
KMD C02 2 1
计算剩余月份的故障,“Y”=(X*剩余月份/12)
超过12个月的总故障=当前故障+Y 因此,预测%=[1-(12个月内的总故障/频率)]*100 在我们的示例中,假设X=2 因此Y=(2*9/12) 预测%=[1-(1+1.5)]*100
Site Code CC B.P.O Forecast StartDate EndDate
ABT A01 01/01/2011 01/02/2012
ABT A02 01/01/2011 19/02/2011
ABT A02 20/02/2011 01/01/2012
ABT A02 02/01/2012 01/01/2013
AFL A02 01/01/2011 01/02/2012
TRG A01 01/01/2011 01/02/2012
TRG K05 01/01/2011 01/02/2012
KLD K05 01/01/2011 15/05/2012
KLD K05 16/05/2012 01/01/2013
KTY K05 01/01/2011 01/02/2012
KMD C02 01/01/2011 01/02/2012
例如:
Site Code CC B.P.O Forecast
A A01
A A02
[i.e.,Avg value of (ABT and A02)
and (AFL and A02)]
T A01
T K05 avg
[i.e., Avg value of (KLD and K05)
and (KTY and K05)]
K K05
K C02
CREATE TABLE Table1
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
Site VARCHAR(5),
Code VARCHAR(5),
FailFlag CHAR(1),
Comments VARCHAR(100),
ModifiedDate DATETIME,
ModifiedBy VARCHAR(50)
);
INSERT INTO Table1
(Site, Code, FailFlag, Comments, ModifiedDate, ModifiedBy)
SELECT 'ABT', 'A01', 'F', 'Dfasdf', '10/11/2011', 'Anna' UNION ALL
SELECT 'ABT', 'A01', 'F', 'dsfsdf', '15/12/2012', 'Mand' UNION ALL
SELECT 'ABT', 'A01', NULL, 'Rds', '30/03/2011', 'Tim' UNION ALL
SELECT 'ABT', 'A01', NULL, 'GHDs', '02/12/2012', 'Andy' UNION ALL
SELECT 'ABT', 'A02', 'F', 'dfd', '09/05/2012', 'Anna' UNION ALL
SELECT 'ABT', 'A02', NULL, 'sdada', '11/02/2013', 'Kathy' UNION ALL
SELECT 'ABT', 'A02', NULL, 'Dfg', '15/05/2011', 'Rob' UNION ALL
SELECT 'AFL', 'A02', 'F', 'asda', '13/02/2011', 'Dan' UNION ALL
SELECT 'AFL', 'A02', NULL, 'dsaa', '24/12/2010', 'Ryan' UNION ALL
SELECT 'TRG', 'A01', NULL, 'sdasd', '16/04/2010', 'Richard' UNION ALL
SELECT 'TRG', 'K05', NULL, 'jksdh', '23/04/2012', 'Mark' UNION ALL
SELECT 'KLD', 'K05', 'F', 'sd', '18/05/2013', 'Jim' UNION ALL
SELECT 'KLD', 'K05', NULL, 'dsfsd', '10/03/2012', 'James' UNION ALL
SELECT 'KLD', 'K05', NULL, 'sdsd', '12/05/2011', 'Luther' UNION ALL
SELECT 'KTY', 'K05', 'F', 'saq', '09/09/2012', 'Ryan' UNION ALL
SELECT 'KTY', 'K05', NULL, 'asd', '04/04/2010', 'Kathy' UNION ALL
SELECT 'KMD', 'C02', 'F', 'nas', '29/02/2012', 'Rob' UNION ALL
SELECT 'KMD', 'C02', NULL, 'asda', '11/11/2011', 'Andy';
表2脚本:
CREATE TABLE Table2
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
Site VARCHAR(5),
Code VARCHAR(5),
Freq int,
StartDate DATETIME,
EndDate DATETIME
);
INSERT INTO Table2 (Site, Code, Freq, StartDate, EndDate)
SELECT 'ABT', 'A01', 43, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'ABT', 'A02', 254, '01/01/2011', '19/02/2011' UNION ALL
SELECT 'ABT', 'A02', 109, '20/02/2011', '01/01/2012' UNION ALL
SELECT 'ABT', 'A02', 12, '02/01/2012', '01/01/2013' UNION ALL
SELECT 'AFL', 'A02', 13, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'TRG', 'A01', 122, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'TRG', 'K05', 61, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'KLD', 'KO5', 33, '01/01/2011', '15/05/2012' UNION ALL
SELECT 'KLD', 'K05', 79, '16/05/2012', '01/01/2013' UNION ALL
SELECT 'KTY', 'K05', 52, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'KMD', 'C02', 78, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'ZYT', 'G01', 11, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'PYN', 'A01', 15, '01/01/2011', '01/02/2012' UNION ALL
SELECT 'DYN', 'F08', 122, '01/01/2011', '01/02/2012';
“有点复杂。”是的
从顶部开始,这是您的第2步。
这可能有一个关键的缺陷,因为它没有限制任何东西持续3年或12个月。从你的问题中不清楚这是什么意图,所以我们将使用这个
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site,Code;
需要将其与表2合并以获得频率场。我将其包装在一个子选择中,并将其称为子查询S2,因为这是第2步
SELECT s2.Site, s2.Code,s2.[Count], S2.FailFlagCount, Table2.Freq
FROM
(
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site,Code
) S2
LEFT JOIN Table2 on S2.Site = table2.Site and S2.Code = table2.Code
;
计算CC和BPO相对容易。上面的代码变成了一个名为S3的子查询
注意,我在这里防止了被零除的错误
SELECT Site, Code, [Count], FailFlagCount, Freq,
CASE WHEN [Count]=0 THEN 0 ELSE ( 1-(FailFlagCount / [Count]))*100 END CC,
CASE WHEN Freq = 0 THEN 0 ELSE ( 1-(FailFlagCount / Freq))*100 END BPO
FROM
(
SELECT s2.Site, s2.Code,s2.[Count], S2.FailFlagCount, ISNULL(Table2.Freq, 1) AS Freq
FROM
(
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site,Code
) S2
LEFT JOIN Table2 on S2.Site = table2.Site and S2.Code = table2.Code
) s3
;
好的,这里有一点实验,围绕SQL month函数,如何计算还有多少个月,以及今年的第一个月
select GETDATE(), month(GETDATE()), 12-MONTH(GETDATE()),
DATEADD(YEAR, -3, GETDATE()),
DATEFROMPARTS (YEAR(GETDATE()),1,1)
;
SELECT s3.Site, s3.Code, [Count], FailFlagCount, Freq,
CASE WHEN [Count]=0 THEN 0 ELSE ( 1-(FailFlagCount / [Count]))*100 END CC,
CASE WHEN Freq = 0 THEN 0 ELSE ( 1-(FailFlagCount / Freq))*100 END BPO,
ISNULL(YBIt.Y, 0) Y,
isnull(currBit.currFails, 0) as currFails
FROM
(
SELECT s2.Site, s2.Code,s2.[Count], S2.FailFlagCount, ISNULL(Table2.Freq, 1) AS Freq
FROM
(
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site,Code
) S2
LEFT JOIN Table2 on S2.Site = table2.Site and S2.Code = table2.Code
) s3
LEFT JOIN
(
SELECT SITE, CODE, count(*) tot, cast(count(*) as float)/36 avg, (cast(count(*) as float)/36) * ((12-MONTH(GETDATE()))/12) Y
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEADD(YEAR, -3, GETDATE())
GROUP BY SITE, CODE
) YBit on S3.Site = Ybit.site AND S3.code = YBit.code
LEFT JOIN
(
SELECT SITE, CODE, COUNT(*) currFails
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEFROMPARTS (YEAR(GETDATE()),1,1)
GROUP BY SITE, CODE
) currBit ON s3.site = currBit.site and s3.code = currBit.code;
;
现在我们可以计算Y数字了——这是表1的全部内容,但在过去36个月内进行了过滤,然后计算出月平均值。当你在这个月中旬运行时,隐性错误可能会在这里蔓延——它不会在月份边界上断裂,它是在过去3年完成的,而不是最后36个月完成的,不包括这个月。
请注意,我必须将count(*)强制转换为浮点,否则它是一个整数,在除法中四舍五入为0
SELECT SITE, CODE, count(*) tot, cast(count(*) as float)/36 avg, (cast(count(*) as float)/36) * ((12-MONTH(GETDATE()))/12) Y
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEADD(YEAR, -3, GETDATE())
GROUP BY SITE, CODE;
我们用同样的方法计算今年的失败率
SELECT SITE, CODE, COUNT(*) currFails
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEFROMPARTS (YEAR(GETDATE()),1,1)
GROUP BY SITE, CODE;
因此,现在我们可以结合上述三个步骤,得到一个包含Y和当前年份的表。注意,这里的ISNULL和左连接用于补偿今年没有失败的站点
select GETDATE(), month(GETDATE()), 12-MONTH(GETDATE()),
DATEADD(YEAR, -3, GETDATE()),
DATEFROMPARTS (YEAR(GETDATE()),1,1)
;
SELECT s3.Site, s3.Code, [Count], FailFlagCount, Freq,
CASE WHEN [Count]=0 THEN 0 ELSE ( 1-(FailFlagCount / [Count]))*100 END CC,
CASE WHEN Freq = 0 THEN 0 ELSE ( 1-(FailFlagCount / Freq))*100 END BPO,
ISNULL(YBIt.Y, 0) Y,
isnull(currBit.currFails, 0) as currFails
FROM
(
SELECT s2.Site, s2.Code,s2.[Count], S2.FailFlagCount, ISNULL(Table2.Freq, 1) AS Freq
FROM
(
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site,Code
) S2
LEFT JOIN Table2 on S2.Site = table2.Site and S2.Code = table2.Code
) s3
LEFT JOIN
(
SELECT SITE, CODE, count(*) tot, cast(count(*) as float)/36 avg, (cast(count(*) as float)/36) * ((12-MONTH(GETDATE()))/12) Y
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEADD(YEAR, -3, GETDATE())
GROUP BY SITE, CODE
) YBit on S3.Site = Ybit.site AND S3.code = YBit.code
LEFT JOIN
(
SELECT SITE, CODE, COUNT(*) currFails
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEFROMPARTS (YEAR(GETDATE()),1,1)
GROUP BY SITE, CODE
) currBit ON s3.site = currBit.site and s3.code = currBit.code;
;
因此,我们可以最终计算预测
SELECT Site, code, [Count], FAilFlagCount, Freq,
CC, BPO, Y, currFails, Y+currFails totF12,
CASE WHEN Freq = 0 then 0 else (1-(( Y+currFails)/ Freq))*100 END Forecast
FROM
(
SELECT s3.Site, s3.Code, [Count], FailFlagCount, Freq,
CASE WHEN [Count]=0 THEN 0 ELSE ( 1-(FailFlagCount / [Count]))*100 END CC,
CASE WHEN Freq = 0 THEN 0 ELSE ( 1-(FailFlagCount / Freq))*100 END BPO,
ISNULL(YBIt.Y, 0) Y,
isnull(currBit.currFails, 0) as currFails
FROM
(
SELECT s2.Site, s2.Code,s2.[Count], S2.FailFlagCount, ISNULL(Table2.Freq, 1) AS Freq
FROM
(
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site, Code
) S2
LEFT JOIN Table2 on S2.Site = table2.Site and S2.Code = table2.Code
) s3
LEFT JOIN
(
SELECT SITE, CODE, count(*) tot, cast(count(*) as float)/36 avg, (cast(count(*) as float)/36) * ((12-MONTH(GETDATE()))/12) Y
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEADD(YEAR, -3, GETDATE())
GROUP BY SITE, CODE
) YBit on S3.Site = Ybit.site AND S3.code = YBit.code
LEFT JOIN
(
SELECT SITE, CODE, COUNT(*) currFails
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEFROMPARTS (YEAR(GETDATE()),1,1)
GROUP BY SITE, CODE
) currBit ON s3.site = currBit.site and s3.code = currBit.code
) S4A
;
好的,我们突然需要开始日期和结束日期。它们在表2中,这似乎也是站点+代码的主列表。让我们做一个主节点,并用左连接将我们的计算连接到主节点。我们还将计算站点类型
这是您对每个站点+代码的详细计算。
select left (t2.site, 1) siteType, t2.site, t2.code,
[Count], FAilFlagCount, s4.Freq,
CC, BPO, Forecast,
T2.StartDate, T2.EndDAte
FROM
Table2 T2
LEFT JOIN
(
SELECT Site, code, [Count], FAilFlagCount, Freq,
CC, BPO, Y, currFails, Y+currFails totF12,
CASE WHEN Freq = 0 then 0 else (1-(( Y+currFails)/ Freq))*100 END Forecast
FROM
(
SELECT s3.Site, s3.Code, [Count], FailFlagCount, Freq,
CASE WHEN [Count]=0 THEN 0 ELSE ( 1-(FailFlagCount / [Count]))*100 END CC,
CASE WHEN Freq = 0 THEN 0 ELSE ( 1-(FailFlagCount / Freq))*100 END BPO,
ISNULL(YBIt.Y, 0) Y,
isnull(currBit.currFails, 0) as currFails
FROM
(
SELECT s2.Site, s2.Code,s2.[Count], S2.FailFlagCount, ISNULL(Table2.Freq, 1) AS Freq
FROM
(
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site, Code
) S2
LEFT JOIN Table2 on S2.Site = table2.Site and S2.Code = table2.Code
) s3
LEFT JOIN
(
SELECT SITE, CODE, count(*) tot, cast(count(*) as float)/36 avg, (cast(count(*) as float)/36) * ((12-MONTH(GETDATE()))/12) Y
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEADD(YEAR, -3, GETDATE())
GROUP BY SITE, CODE
) YBit on S3.Site = Ybit.site AND S3.code = YBit.code
LEFT JOIN
(
SELECT SITE, CODE, COUNT(*) currFails
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEFROMPARTS (YEAR(GETDATE()),1,1)
GROUP BY SITE, CODE
) currBit ON s3.site = currBit.site and s3.code = currBit.code
) S4A
) S4
on t2.site = s4.site and t2.code = s4.code
;
从那里,我们可以很容易地创建平均值
SELECT siteType, '' as site, '' as code, avg([count]) [count], avg(FailFlagCount) FailFlagCount, avg(Freq) Freq,
avg (CC) CC, avg(BPO) BPO, avg(Forecast) Forecast, '' StartDAte, '' EndDate
FROM
(
select left (t2.site, 1) siteType, t2.site, t2.code,
[Count], FAilFlagCount, s4.Freq,
CC, BPO, Forecast,
T2.StartDate, T2.EndDAte
FROM
Table2 T2
LEFT JOIN
(
SELECT Site, code, [Count], FAilFlagCount, Freq,
CC, BPO, Y, currFails, Y+currFails totF12,
CASE WHEN Freq = 0 then 0 else (1-(( Y+currFails)/ Freq))*100 END Forecast
FROM
(
SELECT s3.Site, s3.Code, [Count], FailFlagCount, Freq,
CASE WHEN [Count]=0 THEN 0 ELSE ( 1-(FailFlagCount / [Count]))*100 END CC,
CASE WHEN Freq = 0 THEN 0 ELSE ( 1-(FailFlagCount / Freq))*100 END BPO,
ISNULL(YBIt.Y, 0) Y,
isnull(currBit.currFails, 0) as currFails
FROM
(
SELECT s2.Site, s2.Code,s2.[Count], S2.FailFlagCount, ISNULL(Table2.Freq, 1) AS Freq
FROM
(
SELECT Site,Code,COUNT(*) as [Count],
FailFlagCount= SUM(CASE WHEN FailFlag = 'F' THEN 1 ELSE 0 END)
FROM Table1
GROUP BY Site, Code
) S2
LEFT JOIN Table2 on S2.Site = table2.Site and S2.Code = table2.Code
) s3
LEFT JOIN
(
SELECT SITE, CODE, count(*) tot, cast(count(*) as float)/36 avg, (cast(count(*) as float)/36) * ((12-MONTH(GETDATE()))/12) Y
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEADD(YEAR, -3, GETDATE())
GROUP BY SITE, CODE
) YBit on S3.Site = Ybit.site AND S3.code = YBit.code
LEFT JOIN
(
SELECT SITE, CODE, COUNT(*) currFails
FROM Table1
WHERE FailFlag = 'F'
AND ModifiedDate >= DATEFROMPARTS (YEAR(GETDATE()),1,1)
GROUP BY SITE, CODE
) currBit ON s3.site = currBit.site and s3.code = currBit.code
) S4A
) S4
on t2.site = s4.site and t2.code = s4.code
) S5
GROUP BY siteType
;
或者,您可以用详细的计算填充一个表,然后计算平均值,而不是使用我的最终计算
我将把最后一个联合留给你。“3.我们检查表2中的相同组合。”这意味着什么?我的意思是,我们在表2中寻找相同的“站点”和“代码”组合,以获得完整书面问题的频率+1。但表2中没有“ABT/A02”的频率。在这种情况下,有很多——三个。“ABT/A02”的正确频率值是多少?如果您可以观察到这3行的开始日期和结束日期是不同的。因此,我们考虑所有3行,出于同样的原因,我的第5步将有日期谢谢您GregHNZ如此努力帮助我。这正是我需要的东西。我添加的几个tweek是在计算CC和BPO时,我必须将它们转换为float以获得准确的值。再次感谢。还有一个更新是,我已经完成了按站点类型和代码的最后一组,并在我的查询中包含了Det,因为我们需要获得站点类型和代码的固定组合。我希望我是对的。