在SQL Server中按周细分
鉴于此查询:在SQL Server中按周细分,sql,sql-server-2005,sql-server-2008,Sql,Sql Server 2005,Sql Server 2008,鉴于此查询: DECLARE @FROM_DT DATETIME, @TO_DT DATETIME BEGIN SET @FROM_DT = '10/01/2009' SET @TO_DT = DATEADD(DAY,7,@FROM_DT) --WHILE (@FROM_DT <= '10/01/2010') WHILE (@TO_DT < '10/01/2010') BEGIN SELECT CONVERT(CHAR(10),@FROM_DT,101)
DECLARE
@FROM_DT DATETIME,
@TO_DT DATETIME
BEGIN
SET @FROM_DT = '10/01/2009'
SET @TO_DT = DATEADD(DAY,7,@FROM_DT)
--WHILE (@FROM_DT <= '10/01/2010')
WHILE (@TO_DT < '10/01/2010')
BEGIN
SELECT
CONVERT(CHAR(10),@FROM_DT,101) AS FROM_DT,
CONVERT(CHAR(10),DATEADD(DAY,-1,@TO_DT),101) AS TO_DT,
COUNTRY AS CITZ,
COUNT(SUBJECT_KEY) AS PEOPLE
FROM MYTALE
WHERE DATE_DT >=@FROM_DT
AND DATE_DT <@TO_DT
GROUP BY COUNTRY
SET @FROM_DT = DATEADD(DAY,7,@FROM_DT)
SET @TO_DT = DATEADD(DAY, 7,@TO_DT)
END
END
问题:
SQL中有没有一种方法可以像下面这样编写输出?我需要整合数据。我可以复制和粘贴它们,但这是52周的数据。这不是一个有效的方法,请帮忙。我使用SQLServer2005和2008版本
FROM_DT TO_DT COUNTRY PEOPLE
10/01/2009 10/07/2009 A 2
10/01/2009 10/07/2009 B 1
10/08/2009 10/14/2009 A 1
10/08/2009 10/14/2009 C 2
09/23/2010 09/29/2010 A 1
09/23/2010 09/29/2010 B 3
09/30/2010 10/06/2010 C 13
----
从上面的查询中,我对WHILE@From_DT进行了注释,您可以使用带有union子句的动态查询,但我要做的是创建一个临时表并将结果插入其中。然后您可以从那里选择数据并删除临时表
您的另一个选择是创建一个表,该表保留您的周的从到日期,并加入该表。这实际上是一种更好的方法,但您需要使该表与您需要的所有日期保持最新。您可以使用带有union子句的动态查询,但我要做的是创建一个临时表并将结果插入其中。然后您可以从那里选择数据并删除临时表
您的另一个选择是创建一个表,该表保留您的周的从到日期,并加入该表。这实际上是一种更好的方法,但您需要使该表与您需要的所有日期保持最新。好的,SQL Server有一个名为DATEPART的函数,它还可以为您提供日期的周部分,例如:
SELECT
DATEPART(WEEK, DATE_DT)
Country AS CITZ,
COUNT(Subject_Key) AS PEOPLE
FROM dbo.MyTable
GROUP BY
Country, DATEPART(WEEK, DATE_DT)
这将为您提供数字周数,但尚未提供起始日期和截止日期
或者,您可以不使用基本查询,而是将结果存储到临时表中:
CREATE TABLE dbo.tmp_Results(FromDT CHAR(10), ToDT CHAR(10),
Country VARCHAR(100), Count INT)
然后只需将每次跑步的结果插入该表:
INSERT INTO dbo.tmp_Results(FromDT, ToDT, Country, Count)
SELECT
CONVERT(CHAR(10),@FROM_DT,101) AS FROM_DT,
CONVERT(CHAR(10),DATEADD(DAY,-1,@TO_DT),101) AS TO_DT,
COUNTRY AS CITZ,
COUNT(SUBJECT_KEY) AS PEOPLE
FROM MYTALE
WHERE DATE_DT >=@FROM_DT
AND DATE_DT <@TO_DT
GROUP BY COUNTRY
好的,SQL Server有一个名为DATEPART的函数,它还可以为您提供日期的周部分,例如:
SELECT
DATEPART(WEEK, DATE_DT)
Country AS CITZ,
COUNT(Subject_Key) AS PEOPLE
FROM dbo.MyTable
GROUP BY
Country, DATEPART(WEEK, DATE_DT)
这将为您提供数字周数,但尚未提供起始日期和截止日期
或者,您可以不使用基本查询,而是将结果存储到临时表中:
CREATE TABLE dbo.tmp_Results(FromDT CHAR(10), ToDT CHAR(10),
Country VARCHAR(100), Count INT)
然后只需将每次跑步的结果插入该表:
INSERT INTO dbo.tmp_Results(FromDT, ToDT, Country, Count)
SELECT
CONVERT(CHAR(10),@FROM_DT,101) AS FROM_DT,
CONVERT(CHAR(10),DATEADD(DAY,-1,@TO_DT),101) AS TO_DT,
COUNTRY AS CITZ,
COUNT(SUBJECT_KEY) AS PEOPLE
FROM MYTALE
WHERE DATE_DT >=@FROM_DT
AND DATE_DT <@TO_DT
GROUP BY COUNTRY
数据仓库的一种方法是创建一个周表,其中包含所有可能的周,以及它们的开始和结束日期:
Week StartDate EndDate
1 10/01/2009 10/07/2009
2 10/08/2009 10/14/2009
3 10/15/2009 10/21/2009
...
…然后加入其中。您可以提前填写一次Weeks表-如果您愿意,您可以将其填写到3000年-然后可以在数据库中进行如下查询:
SELECT
StartDate, EndDate, COUNTRY, COUNT(SUBJECT_KEY) AS People
FROM
MYTALE INNER JOIN Weeks ON DATE_DT BETWEEN StartDate AND EndDate
GROUP BY
StartDate, EndDate, Country
当您需要对一系列日期进行数据分析,并且可以预先构建类似的日或月表时,这通常会简化复杂的查询。如果已经对表进行了适当的索引,那么它也可以更快。这些表是星型架构数据仓库术语中的时间维度。数据仓库的一种方法是创建一个周表,其中包含所有可能的周,以及它们的开始和结束日期:
Week StartDate EndDate
1 10/01/2009 10/07/2009
2 10/08/2009 10/14/2009
3 10/15/2009 10/21/2009
...
…然后加入其中。您可以提前填写一次Weeks表-如果您愿意,您可以将其填写到3000年-然后可以在数据库中进行如下查询:
SELECT
StartDate, EndDate, COUNTRY, COUNT(SUBJECT_KEY) AS People
FROM
MYTALE INNER JOIN Weeks ON DATE_DT BETWEEN StartDate AND EndDate
GROUP BY
StartDate, EndDate, Country
当您需要对一系列日期进行数据分析,并且可以预先构建类似的日或月表时,这通常会简化复杂的查询。如果已经对表进行了适当的索引,那么它也可以更快。这些表是星型架构数据仓库术语中的时间维度。请尝试:
DECLARE
@FROM_DT DATETIME,
@TO_DT DATETIME
BEGIN
SET @FROM_DT = '10/01/2009'
SET @TO_DT = DATEADD(DAY,7*53,@FROM_DT)
SELECT
CONVERT(CHAR(10),DATEADD(DAY,7*(WEEKNO),@FROM_DT),101) AS FROM_DT,
CONVERT(CHAR(10),DATEADD(DAY,7*(WEEKNO)+6,@FROM_DT),101) AS TO_DT,
COUNTRY AS CITZ,
COUNT(SUBJECT_KEY) AS PEOPLE
(SELECT M.*, TRUNC(DATEDIFF(DAY,@FROM_DT,DATE_DT)/7) WEEKNO
FROM MYTALE M
WHERE DATE_DT >=@FROM_DT
AND DATE_DT <@TO_DT) SQ
GROUP BY COUNTRY, WEEKNO
END
尝试:
救命啊!不再需要临时表,因为您可以动态生成集合,并且可以在任何日期而不是周一开始工作周 危险:写在记事本上。可能存在小错误/打字错误。不过这主意不错
WITH weeks (start, end) AS (
select
@from_dt as start
dateadd(day, 7, @from_dt) as end
UNION
select
dateadd(day, start, 7)
dateadd(day, end, 7)
from
weeks
where
start < @last_dt
)
select
w.start,
w.end,
c.country,
count(c.subject_key)
from
my_table c
join weeks on c.date_dt >= start and c.date_dt < end
group by
start, end, country
救命啊!不再需要临时表,因为您可以动态生成集合,并且可以在任何日期而不是周一开始工作周 危险:写在记事本上。可能存在小错误/打字错误。不过这主意不错
WITH weeks (start, end) AS (
select
@from_dt as start
dateadd(day, 7, @from_dt) as end
UNION
select
dateadd(day, start, 7)
dateadd(day, end, 7)
from
weeks
where
start < @last_dt
)
select
w.start,
w.end,
c.country,
count(c.subject_key)
from
my_table c
join weeks on c.date_dt >= start and c.date_dt < end
group by
start, end, country