Sql 基于同一子集内的值从子集中选择?
我创建了一个如下表:Sql 基于同一子集内的值从子集中选择?,sql,sql-server,sql-server-2008,select,Sql,Sql Server,Sql Server 2008,Select,我创建了一个如下表: CREATE TABLE #TEMP(RecordDate datetime, First VARCHAR(255), Last VARCHAR(255), Value int) INSERT INTO #TEMP VALUES('2011-03-01 00:00:00.000','john','smith','10') INSERT INTO #TEMP VALUES('2011-03-01 00:00:00.000','john','adams','60') INSE
CREATE TABLE #TEMP(RecordDate datetime, First VARCHAR(255), Last VARCHAR(255), Value int)
INSERT INTO #TEMP VALUES('2011-03-01 00:00:00.000','john','smith','10')
INSERT INTO #TEMP VALUES('2011-03-01 00:00:00.000','john','adams','60')
INSERT INTO #TEMP VALUES('2011-03-01 00:00:00.000','john','resig','90')
INSERT INTO #TEMP VALUES('2011-03-01 00:00:00.000','john','balte','95')
INSERT INTO #TEMP VALUES('2011-03-01 01:00:00.000','john','smith','98')
INSERT INTO #TEMP VALUES('2011-03-01 01:00:00.000','john','adams','67')
INSERT INTO #TEMP VALUES('2011-03-01 01:00:00.000','john','resig','24')
INSERT INTO #TEMP VALUES('2011-03-01 01:00:00.000','john','balte','20')
SELECT * FROM #TEMP
DROP TABLE #TEMP
其中现在包含以下记录:
RecordDate First Last Value
2011-03-01 00:00:00.000 john smith 10
2011-03-01 00:00:00.000 john adams 60
2011-03-01 00:00:00.000 john resig 90
2011-03-01 00:00:00.000 john balte 95
2011-03-01 01:00:00.000 john smith 98
2011-03-01 01:00:00.000 john adams 67
2011-03-01 01:00:00.000 john resig 24
2011-03-01 01:00:00.000 john balte 20
我正在尝试获得如下表:
RecordDate first Good Bad
2011-03-01 00:00:00.000 john 3 1
2011-03-01 01:00:00.000 john 2 2
我计算好的和坏的方法是,取特定日期名字为john的所有人的最大值,然后将其作为特定日期和名字的原始数据集的过滤器。只有大于0.5*MAXValue的值才视为良好
在结果表中,有3个好值,因为第一个日期的最大值为95,只有60,90,95大于0.5*95,因此结果为good,Bad=3,1。在第二个结果中,同样是2,2
我的表足够大,有近3亿条记录,我不知道从哪里开始有效地执行这项操作。有没有关于高效方式的建议
我目前的工作方法但成本高昂,如下所示:
SELECT RecordDate
, FirstName
,
(
SELECT COUNT(*)
FROM #TEMP
WHERE Value > 0.5*(SELECT MAX(Value) FROM #TEMP WHERE RecordDate = A.RecordDate AND FirstName = A.FirstName)
AND RecordDate = A.RecordDate AND FirstName = A.FirstName
) AS Good
,
(
SELECT COUNT(*)
FROM #TEMP
WHERE Value < 0.5*(SELECT MAX(Value) FROM #TEMP WHERE RecordDate = A.RecordDate AND FirstName = A.FirstName)
AND RecordDate = A.RecordDate AND FirstName = A.FirstName
) AS Bad
FROM #TEMP A
GROUP BY RecordDate, FirstName;
给你:
select
t.RecordDate,
COUNT(case
when t.Value > MV.MaxValue * 0.5 then 1
else null
end) Good,
COUNT(case
when t.Value <= MV.MaxValue * 0.5 then 1
else null
end) Bad
from #Temp t inner join
(select RecordDate, MAX(Value) MaxValue
from #Temp Group By RecordDate) MV on t.RecordDate = MV.RecordDate
Group by t.RecordDate
给你:
select
t.RecordDate,
COUNT(case
when t.Value > MV.MaxValue * 0.5 then 1
else null
end) Good,
COUNT(case
when t.Value <= MV.MaxValue * 0.5 then 1
else null
end) Bad
from #Temp t inner join
(select RecordDate, MAX(Value) MaxValue
from #Temp Group By RecordDate) MV on t.RecordDate = MV.RecordDate
Group by t.RecordDate
引用外部查询的嵌套查询可能会导致大量重复工作。 这将一次性计算所有姓名和日期的最大值:
SELECT RecordDate, FirstName, MAX(Value) FROM #TEMP GROUP BY RecordDate, FirstName
现在连接回原始数据:
SELECT A.RecordDate, A.FirstName,
SUM(CASE WHEN Value > MaxVal*0.5 THEN 1 ELSE 0 END) AS GOOD,
SUM(CASE WHEN Value > MaxVal*0.5 THEN 0 ELSE 1 END) AS BAD,
FROM #TEMP A INNER JOIN
(SELECT RecordDate, FirstName, MAX(Value) as MaxVal
FROM #TEMP GROUP BY RecordDate, FirstName) B
ON (A.RecordDate = B.RecordDate AND A.FirstName = B.FirstName)
GROUP BY A.RecordDate, A.FirstName
引用外部查询的嵌套查询可能会导致大量重复工作。 这将一次性计算所有姓名和日期的最大值:
SELECT RecordDate, FirstName, MAX(Value) FROM #TEMP GROUP BY RecordDate, FirstName
现在连接回原始数据:
SELECT A.RecordDate, A.FirstName,
SUM(CASE WHEN Value > MaxVal*0.5 THEN 1 ELSE 0 END) AS GOOD,
SUM(CASE WHEN Value > MaxVal*0.5 THEN 0 ELSE 1 END) AS BAD,
FROM #TEMP A INNER JOIN
(SELECT RecordDate, FirstName, MAX(Value) as MaxVal
FROM #TEMP GROUP BY RecordDate, FirstName) B
ON (A.RecordDate = B.RecordDate AND A.FirstName = B.FirstName)
GROUP BY A.RecordDate, A.FirstName
谢谢你的把戏。我需要按名字对结果进行分组,因此我编辑了您的答案以反映这一点。你介意看一下吗?如果不正确,我将恢复更改。太好了!我很高兴你在我完成我的回答之前发布了你的答案;我正在使用NTILE2,您的回答让我重新检查问题的内容:+是的,我一直很乐意帮忙!谢谢你的把戏。我需要按名字对结果进行分组,因此我编辑了您的答案以反映这一点。你介意看一下吗?如果不正确,我将恢复更改。太好了!我很高兴你在我完成我的回答之前发布了你的答案;我正在使用NTILE2,您的回答让我重新检查问题的内容:+是的,我一直很乐意帮忙!但仍然是+1感谢您的时间。请注意,这使用的是SUM1或0,而不是COUNT1或NULL。您确定NULL不会添加到计数中吗?它会发生:。您的解决方案因使用SUM而有所不同,但它也有效。你应该留下它,因为它可能会帮助未来的访问者。嗯,不。我在内存中工作,没有服务器可以测试。嗯,因为OP发布了代码来实际创建结构和数据,所以我很容易实际运行查询。我可以告诉你,我发布的代码运行平稳:而且,理论上讲,COUNT不应该为null,但仍然是+1感谢您的时间。请注意,这使用的是SUM1或0,而不是COUNT1或NULL。您确定NULL不会添加到计数中吗?它会发生:。您的解决方案因使用SUM而有所不同,但它也有效。你应该留下它,因为它可能会帮助未来的访问者。嗯,不。我在内存中工作,没有服务器可以测试。嗯,因为OP发布了代码来实际创建结构和数据,所以我很容易实际运行查询。我可以告诉你我发布的代码运行顺利:而且,从理论上讲,COUNT不应该计算空值