鉴于此查询:
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
以下是我的结果:
FROM_DT TO_DT COUNTRY PEOPLE
10/01/2009 10/07/2009 A 2
10/01/2009 10/07/2009 B 1
FROM_DT TO_DT COUNTRY PEOPLE
10/08/2009 10/14/2009 A 1
10/08/2009 10/14/2009 C 2
---to
FROM_DT TO_DT COUNTRY PEOPLE
09/23/2010 09/29/2010 A 1
09/23/2010 09/29/2010 B 3
FROM_DT TO_DT COUNTRY PEOPLE
09/30/2010 10/06/2010 C 13
09/30/2010 10/06/2010 D 1
问题:
在SQL中有没有办法可以像下面那样编写输出? (我需要整合数据。我可以复制并粘贴它们,但这是52周的数据。不是一种有效的方法)请帮忙。我使用SQL Server 2005&amp; 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&lt; = '10 / 01/2010')并将其替换为WHILE(@TO_DT&lt; '10 / 01/2010'),因为我想获取FY10的数据,日期从2009年10月1日开始到2010年9月30日。但是,结果仅截至2010年9月29日,不包括2010年9月30日的数据。我的查询有问题吗?请帮忙!
答案 0 :(得分:2)
好吧,SQL Server有一个名为DATEPART
的函数,它还可以为您提供日期的WEEK
部分 - 例如:
SELECT
DATEPART(WEEK, DATE_DT)
Country AS CITZ,
COUNT(Subject_Key) AS PEOPLE
FROM dbo.MyTable
GROUP BY
Country, DATEPART(WEEK, DATE_DT)
这将为您提供数字周数(但尚未包含from_date和to_date)。
或者您可以单独保留基本查询,但将结果存储到临时表中:
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
然后从最后的临时表中选择:
SELECT * FROM dbo.tmp_Results
答案 1 :(得分:2)
递归CTE救援!不再需要临时表,因为你可以动态生成你的设置,并且可以在任何日期而不是在星期一开始几周。
(危险:写在记事本中。可能存在轻微的错误/错别字。但是正确的想法)
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
答案 2 :(得分:1)
您可以使用带有union子句的动态查询,但我要做的是创建一个临时表并将结果插入其中。然后你可以从那里选择数据并删除临时表。
您的另一个选择是创建一个表,该表一直保持几周的起始日期,然后加入该表。这实际上是一种首选方式,但您需要使该表与所需的所有日期保持同步。
答案 3 :(得分:0)
数据仓库的一种方法是创建一个“周”表,其中包含所有可能的周数,以及它们的开始和结束日期:
Week StartDate EndDate
1 10/01/2009 10/07/2009
2 10/08/2009 10/14/2009
3 10/15/2009 10/21/2009
...
...然后加入那个。您可以提前填写“周”表 - 如果需要,可以将其填写到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
当您需要在一系列日期中进行数据分析时,这通常可以简化复杂的查询(并且您可以预先构建类似的“天”或“月”表。)假设您已编入索引,它也可以更快适当的表格。这些表是星型模式数据仓库用语中的“时间维度”。
答案 4 :(得分:0)
尝试:
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