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 行目にも興味がある理由を説明しています) にも関心があります。 )。

日付に最小値と最大値を使用して金額を合計できることはわかっていますが、レコードをそのように分割する方法がわかりません。
ありがとう!

4

6 に答える 6

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

于 2013-07-30T13:13:15.853 に答える
2

ここに1つのアイデアがあります(そしてそれに付随するフィドル):

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

そして2番目、UNIONfiddle)を使用せずに:

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)

于 2013-07-30T13:08:58.553 に答える
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
于 2013-07-30T13:11:34.267 に答える
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フィドル

于 2013-07-30T13:33:58.173 に答える
0

いつお金が入ってきて、いつ止まるかを確認したいだけなら、これでうまくいくかもしれません。

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

ただし、これには、お金が入ってこない期間は含まれません。

于 2013-07-30T13:05:07.570 に答える