2013-07-30 4 views
5

:그룹화 내가이 테이블에 쿼리를 할 노력하고있어

Id  startdate  enddate  amount 
1  2013-01-01 2013-01-31  0.00 
2  2013-02-01 2013-02-28  0.00 
3  2013-03-01 2013-03-31  245 
4  2013-04-01 2013-04-30  529 
5  2013-05-01 2013-05-31  0.00 
6  2013-06-01 2013-06-30  383 
7  2013-07-01 2013-07-31  0.00 
8  2013-08-01 2013-08-31  0.00 

내가 출력을 얻으려면이 :

2013-01-01   2013-02-28   0 
2013-03-01   2013-06-30   1157 
2013-07-01   2013-08-31   0 

그 결과를 얻고 싶었다 그래서 돈이 언제 들어 왔는지와 멈출 때를 알았습니다. 저는 또한 돈이 들어 오기 시작하기 전의 달 수 (첫 번째 행을 설명 함)와 돈이 중단 된 달 수에 관심이 있습니다 (2013 년 7 월 ~ 2013 년 8 월 3 행에도 왜 관심이 있는지 설명합니다).).

나는 날짜와 금액의 합계에 최소값과 최대 값을 사용할 수 있지만 레코드를 이렇게 나누는 방법을 알 수는 없다는 것을 알고 있습니다.
감사합니다.

+1

감사합니다. 나는 안드로이드 폰에서 질문을하려고 애썼다. –

+2

그룹화를 원하십니까? –

+2

0과 0이 아닌 연속적인 행을 그룹화하는 것처럼 보이지만 왜 5 월 행을 분리하지 않습니까? –

답변

2

여기 (그것으로 이동하고 a fiddle) 하나 개의 아이디어 :

;WITH MoneyComingIn AS 
(
    SELECT MIN(startdate) AS startdate, MAX(enddate) AS enddate, 
     SUM(amount) AS amount 
    FROM myTable 
    WHERE amount > 0 
) 
SELECT MIN(startdate) AS startdate, MAX(enddate) AS enddate, 
    SUM(amount) AS amount 
FROM myTable 
WHERE enddate < (SELECT startdate FROM MoneyComingIn) 
UNION ALL 
SELECT startdate, enddate, amount 
FROM MoneyComingIn 
UNION ALL 
SELECT MIN(startdate) AS startdate, MAX(enddate) AS enddate, 
    SUM(amount) AS amount 
FROM myTable 
WHERE startdate > (SELECT enddate FROM MoneyComingIn) 

그리고 두 번째, UNION (fiddle)를 사용하지 않고 :

SELECT MIN(startdate), MAX(enddate), SUM(amount) 
FROM 
(
    SELECT startdate, enddate, amount, 
    CASE 
     WHEN EXISTS(SELECT 1 
        FROM myTable b 
        WHERE b.id>=a.id AND b.amount > 0) THEN 
      CASE WHEN EXISTS(SELECT 1 
          FROM myTable b 
          WHERE b.id<=a.id AND b.amount > 0) 
       THEN 2 
       ELSE 1 
      END 
     ELSE 3 
    END AS partition_no 
    FROM myTable a 
) x 
GROUP BY partition_no 

을 서면으로 내 생각하지만, Id이 순서대로 있다고 가정합니다. 이것을 ROW_NUMBER() OVER(ORDER BY startdate)으로 대체 할 수 있습니다.

select min(startdate), max(enddate), sum(amount) from paiements 
    where enddate < (select min(startdate) from paiements where amount >0) 
union 
select min(startdate), max(enddate), sum(amount) from paiements 
    where startdate >= (select min(startdate) from paiements where amount >0) 
    and enddate <= (select max(enddate) from paiements where amount >0) 
union 
select min(startdate), max(enddate), sum(amount) from paiements 
    where startdate > (select max(enddate) from paiements where amount >0) 

을하지만보고 이런 종류의, 그것은 여러 쿼리를 사용하여 아마 더 명시 적입니다 : 그런

+0

+1 'UNION' 또는 변수를 사용해야하는 솔루션은 없습니다. – Yuck

+0

UNION이없는 좋은 솔루션입니다. –

0

돈에 오기 시작하고 중지 할 때,이 당신을 위해 작동 할 때 당신이 원하는 모든 볼 경우 :

select 
    min(startdate), 
    max(enddate), 
    sum(amount) 
where 
    amount > 0 

이 돈이 생각에오고 있었던 기간을 포함하지 것이다 .

+0

이것은 처음 시작일, 마지막 종료일 및 총 금액을 알려 드릴 것입니다. [link] (http://www.sqlfiddle.com/#!3/c0d17/4) – Sam

+0

예, OP가 명시한대로 : " 그 결과를 얻기 위해 언제 돈이 들어 오기 시작했는지 그리고 멈출 때를 알았습니다. " 앞뒤의 공백을 뺀 부분은 다음과 같습니다. –

1

뭔가를해야한다. 이것은 당신이 원하는 것을

1

:

-- determine the three periods 
DECLARE @StartMoneyIn INT 
DECLARE @EndMoneyIn INT 

SELECT @StartMoneyIn = MIN(Id) 
FROM [Amounts] 
WHERE amount > 0 

SELECT @EndMoneyIn = MAX(Id) 
FROM [Amounts] 
WHERE amount > 0 

-- retrieve the amounts 
SELECT MIN(startdate) AS startdate, MAX(enddate) AS enddate, SUM(amount) AS amount 
FROM [Amounts] 
WHERE Id < @StartMoneyIn 
UNION 
SELECT MIN(startdate), MAX(enddate), SUM(amount) 
FROM [Amounts] 
WHERE Id >= @StartMoneyIn AND Id <= @EndMoneyIn 
UNION 
SELECT MIN(startdate), MAX(enddate), SUM(amount) 
FROM [Amounts] 
WHERE Id > @EndMoneyIn 
4
with CT as 
(
    select t1.*, 
      (select max(endDate) 
      from t 
      where startDate<t1.StartDate and SIGN(amount)<>SIGN(t1.Amount) 
      ) as GroupDate 
    from t as t1 
) 
select min(StartDate) as StartDate, 
     max(EndDate) as EndDate, 
     sum(Amount) as Amount 
from CT 
group by GroupDate 
order by StartDate 

SQLFiddle demo

+0

매우 유용한 검색어입니다. 비록이 사이에 0에 대한 레코드를 반환합니다. –

0

당신이 기간에 전체에 대한 상관 없어,하지만 당신은 0에서 무언가로 이동 레코드를 원하는 경우 그 반대의 경우에는 다음과 같이 무언가를 할 수 있습니다.

select * 
from MoneyTable mt 
where exists (select * 
       from MoneyTable mtTemp 
       where mtTemp.enddate = dateadd(day, -1, mt.startDate) 
       and mtTemp.amount <> mt.amount 
       and mtTemp.amount * mt.amount = 0) 

또는 첫 번째 기록 : 편집 마흐무드 가말에 대한

select * 
from MoneyTable mt 
where exists (select * 
       from MoneyTable mtTemp 
       where mtTemp.enddate = dateadd(day, -1, mt.startDate) 
       and mtTemp.amount <> mt.amount 
       and mtTemp.amount * mt.amount = 0) 
or not exists (select * 
       from MoneyTable mtTemp 
       where mtTemp.enddate = dateadd(day, -1, mt.startDate)) 

Sql Fiddle

관련 문제