给出以下表结构:
CrimeID | No_Of_Crimes | CrimeDate | Violence | Robbery | ASB
1 1 22/02/2011 Y Y N
2 3 18/02/2011 Y N N
3 3 23/02/2011 N N Y
4 2 16/02/2011 N N Y
5 1 17/02/2011 N N Y
是否有可能使用T-SQL生成与此类似的结果集?
Category | This Week | Last Week
Violence 1 3
Robbery 1 0
ASB 3 1
如果上周的数据低于'20 / 02/2011',本周应该大于或等于'20 / 02/2011'
我不是在寻找有人为我编写代码,虽然代码片段会很方便:),只是一些关于这是否可行的建议,以及我应该如何使用SQL Server。
有关信息,我目前正在使用Web服务器上的LINQ执行所有此聚合,但这需要在每次发出此请求时通过网络发送19MB。 (该表有很多类别,并且> 150,000行)。我想让数据库完成所有工作,只通过网络发送少量数据
非常感谢
答案 0 :(得分:3)
编辑删除了错误的sql 编辑忘记上面的尝试以下
select *
from (
select wk, crime, SUM(number) number
from (
select case when datepart(week, crimedate) = datepart(week, GETDATE()) then 'This Week'
when datepart(week, crimedate) = datepart(week, GETDATE())-1 then 'Last Week'
else 'OLDER' end as wk,
crimedate,
case when violence ='Y' then no_of_crimes else 0 end as violence,
case when robbery ='Y' then no_of_crimes else 0 end as robbery,
case when asb ='Y' then no_of_crimes else 0 end as asb
from crimetable) as src
UNPIVOT
(number for crime in
(violence, robbery, asb)) as pivtab
group by wk, crime
) z
PIVOT
( sum(number)
for wk in ([This Week], [Last Week])
) as pivtab
答案 1 :(得分:2)
晚会,但是具有最佳查询计划的解决方案:
示例数据
create table crimes(
CrimeID int, No_Of_Crimes int, CrimeDate datetime,
Violence char(1), Robbery char(1), ASB char(1));
insert crimes
select 1,1,'20110221','Y','Y','N' union all
select 2,3,'20110218','Y','N','N' union all
select 3,3,'20110223','N','N','Y' union all
select 4,2,'20110216','N','N','Y' union all
select 5,1,'20110217','N','N','Y';
制作更多数据 - 除了上面的5个之外,总共约10240行,每个5个在前一个5之前的2周。还创建一个有助于crimedate
的索引。
insert crimes
select crimeId+number*5, no_of_Crimes, DATEADD(wk,-number*2,crimedate),
violence, robbery, asb
from crimes, master..spt_values
where type='P'
create index ix_crimedate on crimes(crimedate)
从这里开始,检查每个的输出以查看它的去向。还要检查执行计划。
Standard Unpivot打破类别。
select CrimeID, No_Of_Crimes, CrimeDate, Category, YesNo
from crimes
unpivot (YesNo for Category in (Violence,Robbery,ASB)) upv
where YesNo='Y'
注意:
再次展开,但这次只选择上周和本周的数据。
select CrimeID, No_Of_Crimes, Category,
Week = sign(datediff(d,CrimeDate,w.firstDayThisWeek)+0.1)
from crimes
unpivot (YesNo for Category in (Violence,Robbery,ASB)) upv
cross join (select DATEADD(wk, DateDiff(wk, 0, getdate()), 0)) w(firstDayThisWeek)
where YesNo='Y'
and CrimeDate >= w.firstDayThisWeek -7
and CrimeDate < w.firstDayThisWeek +7
注意:
(select DATEADD(wk, DateDiff(wk, 0, getdate()), 0)) w(firstDayThisWeek)
创建一个单列表,其中列包含此查询的关键日期,即当前周的第一天(使用DATEFIRST设置)Sign()
只是将数据分成3个桶(-1 / 0 / + 1)。添加+0.1可确保只有两个桶-1和+1。最终查询,按此/上周转动
select Category, isnull([1],0) ThisWeek, isnull([-1],0) LastWeek
from
(
select Category, No_Of_Crimes,
Week = sign(datediff(d,w.firstDayThisWeek,CrimeDate)+0.1)
from crimes
unpivot (YesNo for Category in (Violence,Robbery,ASB)) upv
cross join (select DATEADD(wk, DateDiff(wk, 0, getdate()), -1)) w(firstDayThisWeek)
where YesNo='Y'
and CrimeDate >= w.firstDayThisWeek -7
and CrimeDate < w.firstDayThisWeek +7
) p
pivot (sum(No_Of_Crimes) for Week in ([-1],[1])) pv
order by Category Desc
输出
Category ThisWeek LastWeek
--------- ----------- -----------
Violence 1 3
Robbery 1 0
ASB 3 3
答案 2 :(得分:0)
我会试试这个:
declare @FirstDayOfThisWeek date = '20110220';
select cat.category,
ThisWeek = sum(case when cat.CrimeDate >= @FirstDayOfThisWeek
then crt.No_of_crimes else 0 end),
LastWeek = sum(case when cat.CrimeDate >= @FirstDayOfThisWeek
then 0 else crt.No_of_crimes end)
from crimetable crt
cross apply (values
('Violence', crt.Violence),
('Robbery', crt.Robbery),
('ASB', crt.ASB))
cat (category, incategory)
where cat.incategory = 'Y'
and crt.CrimeDate >= @FirstDayOfThisWeek-7
group by cat.category;