2011-12-06 2 views
1

에 분에서 날짜를 생성 : 항목의두 열에서 최소값과 최대 값을 찾습니다. 내가 SQL 서버 DB에 테이블이 최대

Month Year Open Close 
01  2010 2  0 
02  2010 0  0 
03  2010 0  1 
04  2010 0  0 
05  2010 0  0 
06  2010 0  0 
07  2010 0  0 
08  2010 0  0 
09  2010 0  0 
10  2010 0  0 
11  2010 0  0 
12  2010 0  0 
01  2011 1  0 
02  2011 0  1 

금액 결과 세트 같음에 :

ID Open_date  Close_date 
1  01-01-2010 01-03-2010 
2  21-01-2011 12-02-2011 
3  01-03-2010 NULL 
4  10-01-2010 NULL 

내가 돌아갑니다 약간의 T-SQL 쿼리를 만들 필요가 DB의 테이블의 'Open_date'및 'Close_date'열의 최소값과 동일한 열의 최대 값 사이의 월간 금액입니다. 문제는 두 개의 날짜 열에서 최소 및 최대 값을 찾고 min에서 max까지 날짜를 생성 한 다음이 임시 테이블을 사용하여 임시 테이블의 모든 날짜에 대해 열린 항목과 닫힌 항목의 수를 계산하는 방법입니다.

+0

을 시도 할 수 있습니다? – Lamak

+0

죄송합니다, 실수. 그것을 정정했다. – sunprophit

+0

2010 년 3 월 라인은 1, 1이 아닌 0, 1이 레코드 # 3을 반영해야한다고 생각하십니까? – Tarwn

답변

0

다른 날짜 시스템을 사용하고 있기 때문에 날짜가 약간 변경되었지만 작동해야합니다. 받아들이면 제발!

DECLARE @TABLE1 TABLE 
(
    ID INT 
    , Open_date DATETIME 
    , Close_date DATETIME 
) 

INSERT INTO @TABLE1 (ID, Open_date, Close_date) 
     SELECT 1, '01-01-2010', '03-01-2010' 
UNION SELECT 2, '01-21-2011', '02-12-2011' 
UNION SELECT 3, '03-01-2010', NULL 
UNION SELECT 4, '01-10-2010', NULL 


DECLARE @MIN_DATE DATETIME 
DECLARE @MAX_DATE DATETIME 

SELECT @MIN_DATE = MIN(d) 
    , @MAX_DATE = MAX(d) 
FROM 
(
    SELECT Open_date AS d 
    FROM @TABLE1 

     UNION 

    SELECT Close_date AS d 
    FROM @TABLE1 
)a 

--SELECT @MIN_DATE, @MAX_DATE 



DECLARE @DATES TABLE 
(
    ID INT IDENTITY(1,1) 
    , [date] DATETIME 
) 

DECLARE @DATE DATETIME 
SET @DATE = @MIN_DATE 

WHILE (@DATE <= @MAX_DATE) 
BEGIN 

    INSERT INTO @DATES ([date]) 
    VALUES (@DATE) 

    SET @DATE = @DATE + 1 

END 

--SELECT * 
--FROM @DATES 

SELECT MONTH(a.[date]) AS [Month] 
    , YEAR(a.[date]) AS [Year] 
    , SUM(CASE WHEN b.Open_date IS NOT NULL THEN 1 ELSE 0 END) AS [Open] 
    , SUM(CASE WHEN b.Close_date IS NOT NULL THEN 1 ELSE 0 END) AS [Close] 
FROM @DATES a 
LEFT JOIN @TABLE1 b 
    ON a.[date] = b.Open_date 
GROUP BY YEAR(a.[date]), MONTH(a.[date]) 
ORDER BY YEAR(a.[date]), MONTH(a.[date]) 
1

나는 샘플 데이터의 날짜는 YYYYMMDD를 반영하도록 변경되어 이전의 예를 흥분하고 게시하지 결국,하지만 다시 와서 어쨌든 그것을 게시 :)

-- Sample Data 
CREATE TABLE #SampleVals (ID int, Open_Date Date, Close_Date Date); 
INSERT INTO #SampleVals(ID, Open_Date, Close_Date) 
VALUES(1,'20100101','20100301'), 
     (2,'20110121','20110212'), 
     (3,'20100301', NULL), 
     (4,'20100110',NULL); 

-- Get Start/End for full date range 
DECLARE @Min Date, @Max Date; 
SELECT @Min = DateAdd(dd,-1 * Day(MIN(Open_Date)) + 1, MIN(Open_Date)), 
     @Max = MAX(Close_Date) 
FROM #SampleVals; 

-- Query for values across entire range 
WITH DateRange (StartDate,NextDate) AS (
    SELECT DATEADD(MONTH, n-1, @Min), 
      DATEADD(MONTH, n, @Min) 
    FROM dbo.Number N 
    WHERE N.n <= DATEDIFF(MONTH,@Min,@Max) + 1 
) 
SELECT MONTH(DR.StartDate), 
     YEAR(DR.StartDate), 
     SUM(CASE WHEN S.Open_Date >= DR.StartDate Then 1 Else 0 END) AS [Open], 
     SUM(CASE WHEN S.Close_Date < DR.NextDate Then 1 Else 0 END) AS [Closed] 
FROM DateRange DR 
    LEFT JOIN #SampleVals S ON S.Open_Date < DR.NextDate 
          AND (S.Close_Date >= DR.StartDate OR S.Close_Date IS NULL) 
GROUP BY DR.StartDate 
ORDER BY DR.StartDate; 

-- Cleanup sample data 
DROP TABLE #SampleVals; 

결정 . 또한 로컬 번호 테이블 사용 : Norla 내가이 일을 완성하기 전에 이전에 이루어 졌던 것에

CREATE TABLE dbo.Number(n INT NOT NULL IDENTITY) ; 
GO 
SET NOCOUNT ON ; 
INSERT dbo.Number DEFAULT VALUES ; 
WHILE SCOPE_IDENTITY() < 5000 
    INSERT dbo.Number DEFAULT VALUES ; 

나는 거의이 게시되지 않은, 그러나 시작 날짜가 닫힌 경우 나는 Norla의 솔루션을 닫기 열을 채 웁니다 발견 (그리고 해당 시작 날짜의 달 동안)이 버전은 close_date의 달에 가까운 월 열을 채우는 반면, 나는 당신이 요구 한 것이라고 믿습니다.

SQL 서버 2005 +의 경우
0

, 당신은 1 월 2010에 닫힌 왜 ID를 계산됩니다

somewhat simpler approach. Try this: 

WITH CTE AS 
(
    SELECT MIN(CONVERT(VARCHAR(6),Dates,112)) YearMonth, 
      MAX(CONVERT(VARCHAR(6),Dates,112)) MaxDate 
    FROM ( SELECT Open_Date Dates FROM YourTable 
      UNION 
      SELECT Close_Date FROM YourTable) A 
    UNION ALL 
    SELECT CONVERT(VARCHAR(6),DATEADD(MONTH,1,YearMonth+'01'),112), MaxDate 
    FROM CTE 
    WHERE CONVERT(VARCHAR(6),DATEADD(MONTH,1,YearMonth+'01'),112)<=MaxDate 
) 
SELECT RIGHT(A.YearMonth,2) [Month], LEFT(A.YearMonth,4) [Year], 
     COUNT(B.Id) [Open], COUNT(C.Id) [Close] 
FROM CTE A 
LEFT JOIN YourTable B 
ON A.YearMonth = CONVERT(VARCHAR(6),B.Open_Date,112) 
LEFT JOIN YourTable C 
ON A.YearMonth = CONVERT(VARCHAR(6),C.Close_Date,112) 
GROUP BY RIGHT(A.YearMonth,2), LEFT(A.YearMonth,4) 
ORDER BY LEFT(A.YearMonth,4), RIGHT(A.YearMonth,2) 
0

또 다른 버전

;with T(monthstart, monthend, _tempmax) as (
    select 
     min(Open_date), dateadd(day, -1, dateadd(month, 1, min(Open_date))), dateadd(month, 1, max(Open_date)) as _tempmax from THETABLE 
    union all 
    select 
     dateadd(month, 1, monthstart), dateadd(day, -1, dateadd(month, 2, monthstart)), _tempmax 
    from T 
    where dateadd(month, 1, monthstart) <= _tempmax 
) 
select 
    month(monthstart) as [month], 
    year(monthstart) as [year], 
    sum(case when Open_date between monthstart and monthend then 1 else 0 end), 
    sum(case when Close_date between monthstart and monthend then 1 else 0 end) 
from T 
left join 
    THETABLE on (Open_date between monthstart and monthend) or (Close_date between monthstart and monthend) 
group by 
    month(monthstart), 
    year(monthstart) 
관련 문제