Как показать весь год, месяцы в виде целых между двумя датами? - PullRequest
2 голосов
/ 25 августа 2011

В SQL Server 2000 мне нужно перечислить год, месяц в виде целых чисел в таблице временных показателей из заказов клиента.

Если месяц не существует, мне все равно нужно указать год, месяц, $ 0.00.

Каков наилучший способ сделать это в SQL Server 2000?

01/01/2010 до 07/01/2010 даст:

__Year__, __Month__ , __Billed__
2010,1,$5000.00
2010,2,$6000.00
2010,3,$8000.00
2010,4,$0.00
2010,5,$4000.00
2010,6,$4500.00

с использованием этого кода:

select grp.* from 
(
    select year(orderdate) as yr, 
           month(orderdate) as mn, 
           sum(billed) 
    from Orders 
    group by year(orderdate), month(orderdate), billed 
) grp
order grp.yr, grp.mn

Есть ли простое решение, чтобы не пропускать месяцы, когда не было выставления счетов, и добавлять 0,00 $?

Ответы [ 2 ]

5 голосов
/ 25 августа 2011

Для 2005+ (извините, я пропустил требование 2000 года):

DECLARE @Orders TABLE(OrderDate DATETIME, billed INT);

INSERT @Orders SELECT '20100104', 500
         UNION SELECT '20100106', 700;

DECLARE 
  @year INT, 
  @end_month TINYINT;

SELECT 
  @year = 2010, 
  @end_month = 7;

WITH s(n) AS 
(
  SELECT TOP (@end_month) ROW_NUMBER() OVER (ORDER BY [object_id])
    FROM sys.objects ORDER BY [object_id]
),
m(s) AS
(
  SELECT DATEADD(MONTH, n-1, DATEADD(YEAR, @year-1900, 0)) 
    FROM s
)
SELECT 
    [Year]  = @year, 
    [Month] = MONTH(m.s),
    Billed  = COALESCE(SUM(t.billed), 0)
FROM m
  LEFT OUTER JOIN @Orders AS t
  ON t.OrderDate >= m.s
  AND t.OrderDate < DATEADD(MONTH, 1, m.s)
GROUP BY
  MONTH(m.s)
  ORDER BY [Year], [Month];

Для 2000 года это только немного отличается:

CREATE TABLE #Orders(OrderDate DATETIME, billed INT);

INSERT #Orders SELECT '20100104', 500
         UNION SELECT '20100106', 700;

DECLARE 
  @year INT, 
  @end_month TINYINT;

SELECT 
  @year = 2010, 
  @end_month = 7;

SELECT 
    [year]  = @year, 
    [month] = MONTH(m.s),
    billed  = COALESCE(SUM(t.billed), 0)
FROM 
(
    SELECT s = DATEADD(MONTH, n-1, DATEADD(YEAR, @year-1900, 0)) FROM 
    (
        SELECT DISTINCT TOP 12 n = number
          FROM master..spt_values 
          WHERE number BETWEEN 1 AND @end_month
              ORDER BY number
    ) 
    AS s
) AS m
LEFT OUTER JOIN #Orders AS t
ON t.OrderDate >= m.s
AND t.OrderDate < DATEADD(MONTH, 1, m.s)
GROUP BY MONTH(m.s);

Теперь по общему признанию у меня нет экземпляра 2000удобно для проверки - это просто с манжеты.

3 голосов
/ 25 августа 2011

Составьте таблицу чисел, содержащую числа от 0 до 100 000 или что-либо еще.

Тогда как то так:

DECLARE @StartDate AS DATE
DECLARE @EndDate AS DATE

SELECT YEAR(DATEADD(m, Numbers.N, @StartDate))
    ,MONTH(DATEADD(m, Numbers.N, @StartDate))
    ,ISNULL(OrderSummary.Billed, 0) AS Billed
FROM Numbers
LEFT JOIN (
    SELECT year(orderdate), month(orderdate), sum(billed)
    FROM Orders
    GROUP by year(orderdate), month(orderdate)
) AS OrderSummary (Yr, Mn, Billed)
ON YEAR(DATEADD(m, Numbers.N, @StartDate)) = OrderSummary.Yr
    AND MONTH(DATEADD(m, Numbers.N, @StartDate)) = OrderSummary.Mn
WHERE Numbers.N < DATEDIFF(m, @StartDate, @EndDate)

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

...