разбить на недели в SQL Server - PullRequest
       0

разбить на недели в SQL Server

0 голосов
/ 16 ноября 2010

Учитывая этот запрос:

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 и 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 <= '10 / 01/2010 ') и заменил его на WHILE (@TO_DT <'10 / 01/2010'), потому что я хотел бы получить данные только за 2010 финансовый год, дата которых начинается с 01.10.2009 г. по 30.09.2010 г. Однако результат только до 29.09.2010 г., данные от 30.09.2010 г. не включены. Что-то не так с моим запросом? Пожалуйста, помогите! </p>

Ответы [ 5 ]

2 голосов
/ 16 ноября 2010

рекурсивные 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 голосов
/ 16 ноября 2010

Ну, в 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 голос
/ 16 ноября 2010

Вы можете использовать динамический запрос с предложением объединения, но я бы создал временную таблицу и вставил в нее ваши результаты. Затем вы можете выбрать данные и удалить временную таблицу.

Другим вариантом будет создание таблицы, в которой будут сохранены даты начала ваших недель, и вместо этого присоединиться к ней. Это на самом деле предпочтительный способ сделать это, но вам нужно будет поддерживать эту таблицу в актуальном состоянии со всеми необходимыми датами.

0 голосов
/ 16 ноября 2010

Попробуйте:

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
0 голосов
/ 16 ноября 2010

Подход из хранилища данных будет состоять в том, чтобы создать таблицу «Недели» со всеми возможными неделями в ней, а также датами их начала и окончания:

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 

Это часто упрощает сложные запросы, когда вам нужно выполнить анализ данных за диапазон дат (и вы можете предварительно построить аналогичную таблицу «дни» или «месяцы»). Это также может быть быстрее, если вы проиндексировали таблицы соответственно. Эти таблицы являются «измерениями времени» на языке хранилища данных схемы типа «звезда».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...