2013-07-30 40 views
5

:gruplama Bu tabloya bir sorgu yapmaya çalışıyorum

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 

ben çıkışını almak istiyorum:

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

O sonuç almak istediğini bu yüzden paranın ne zaman gelmeye başladığını ve ne zaman durduğunu bileceğim. Ayrıca paranın gelmeye başladığı ayların (ilk satırı açıklayan) ve paranın durduğu ayların sayısıyla da ilgileniyorum (bu da neden Temmuz 2013'te Ağustos 2013'e kadar 3. sıraya ilgi duyduğumu açıklıyor)).

Min ve max'ı tarihler ve tutarlar üzerinden kullanabileceğimi biliyorum, ancak kayıtların bu şekilde nasıl bölüneceğini anlayamıyorum.
Teşekkürler!

+1

teşekkürler. Soruyu android telefonumdan sormaya çalışıyordum. –

+2

Gruplandırmayı ne yapmak istiyorsunuz? –

+2

Sıfır ve sıfırdan farklı satırları gruplandırmak istediğiniz gibi görünüyor, ancak Mayıs satırını neden ayırmıyorsunuz? –

cevap

2

İşte (onunla gitmek için ve a fiddle) bir fikir:

;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) 

Ve ikinci, UNION (fiddle) kullanmadan:

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 

bunu yazılı olarak herhalde rağmen Id'un sırada olduğunu varsayar. Bunu ROW_NUMBER() OVER(ORDER BY startdate) ile değiştirebilirsiniz.

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) 

Ama raporlama bu tür, Birden sorguları kullanarak muhtemelen daha açık var: Böyle

+0

+1 Bu çözümlerin hiçbiri 'UNION 'veya değişkenler kullanmamalıdır. UNION olmadan – Yuck

+0

iyi bir çözüm. –

0

para geliyor başladı ve durduğunda, bu sizin için işe yarayabilecek ne zaman yapmak istediğin görmek için ise:

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

Bu para olsa gelen yoktu dönemleri dahil olmaz .

+0

Bu sadece ilk başlangıç, son bitiş tarihi ve toplam miktarını verecektir: [link] (http://www.sqlfiddle.com/#!3/c0d17/4) – Sam

+0

Evet, ama OP'nin belirttiği gibi: "İstedim Bu sonuca ulaşmak için paranın ne zaman gelmeye başladığını ve ne zaman durduğunu bileceğim. Eksi öncesi ve sonrasındaki boş dönemler, yani bu :) –

1

şey yapmalı. İstediğin bu mu

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

oldukça kullanışlı bir sorgu. Her ne kadar bu arada arada sıfırlar için kayıt döndürür. –

0

Eğer dönemde toplam umurumda değil, ama yalnızca 0'dan şey gidin kayıtları istiyorsanız

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) 

Yoksa önce içermelidir eğer: ve Vica tersi, böyle çılgınca bir şey yapabileceğini Kayıt: düzenlemek Mahmoud Gamal için

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

İlgili konular