【问题标题】:SQL - combine consecutive date rows based on columnSQL - 根据列组合连续的日期行
【发布时间】:2015-08-31 19:08:09
【问题描述】:

假设我有以下 SQL 结果

BegDate | EndDate | quanitty
1/1/2014  1/31/2014    1
2/1/2014  2/28/2014    1
3/1/2014  3/31/2014    2
4/1/2014  4/30/2014    4
5/1/2014  5/31/2014    4
6/1/2014  6/30/2014    4
7/1/2014  7/31/2014    2
8/1/2014  8/30/2014    2

我需要将具有相同数量的所有月份分组为一行,因此结果应该是

BegDate | EndDate | quanitty
1/1/2014  2/28/2014    1
3/1/2014  3/31/2014    2
4/1/2014  6/30/2014    4
7/1/2014  8/30/2014    2

我搜索了 stackoverflow 并找到了类似的帖子,我尝试过的解决方案无济于事 ThisThis

以下是我用来创建结果的 SQL,其中 term_start 将是我的开始时间,而 term_end 将是我的结束时间。如果您有任何建议,请告诉我。这是我在 SSRS 报告中使用的数据集,如果在 SSRS 报告方面有更简单的方法来执行此操作,那么我可以选择......谢谢!

SELECT 
collaboration = t.collaboration
, trade = t.trade
,  position = p.position
, buyer = CASE WHEN ((p.positiontype = 'BUY') OR (p.positiontype = 'SWAP' AND p.swaptype = 'BUY')) THEN co.name
                WHEN ((p.positiontype = 'SELL') OR (p.positiontype = 'SWAP' AND p.swaptype = 'SELL')) THEN cp.name
            END
, seller = CASE WHEN ((p.positiontype = 'SELL') OR (p.positiontype = 'SWAP' AND p.swaptype = 'SELL')) THEN co.name
                WHEN ((p.positiontype = 'BUY') OR (p.positiontype = 'SWAP' AND p.swaptype = 'BUY')) THEN cp.name 
            END
, trade_date = t.tradedate
, timezone = t.timezone
, delivery_point = isnull(pp.point,'')
------------TABLE DATA BELOW------------
, currency = f.currency
, currency_unit = f.unit
, term_start = CASE WHEN pq.quantitystatus = 'TRADE' THEN pq.begtime ELSE 0 END
, term_end = CASE WHEN pq.quantitystatus = 'TRADE' THEN dateadd(dd,-1,pq.endtime) ELSE 0 END 
, hours =   CASE 
            WHEN ls.loadshape is not null and ls.granularity = 'LOAD' and lsq.loadshape is not null THEN 'Hour Ending (HE) ' + CONVERT(VARCHAR,lsq.beghour + 1) + '00 through HE ' + CONVERT(VARCHAR, lsq.endhour) + '00 (' + CONVERT(VARCHAR, lsq.endhour-lsq.beghour-1) +' Hours each day), Monday Through Sunday, including NERC holidays; ' + tz.description
            WHEN ls.loadshape is not null and ls.granularity = 'LOAD' and lsq.loadshape is null THEN 'See attached schedule'
            WHEN ls.loadshape is not null and ls.granularity = 'PROFILE' THEN 'See attached schedule' 
            ELSE btz.cpn_description  END
, quantity = CASE 
            WHEN ls.loadshape is not null and ls.granularity = 'LOAD' and lsq.loadshape is not null THEN CONVERT(VARCHAR,convert(double precision, lsq.quantity))
            WHEN ls.loadshape is not null and ls.granularity = 'LOAD' and lsq.loadshape is null THEN 'See attached schedule'
            WHEN ls.loadshape is not null and ls.granularity = 'PROFILE' THEN 'See attached schedule' 
            ELSE CONVERT(VARCHAR,convert(double precision, pq.energy))   END    
, product = pr.producttype
, unit = CASE isnull(p.unit,'') WHEN 'dth' THEN 'Dth' WHEN 'kwh' THEN 'kWh' WHEN 'kwm' THEN 'kWm' WHEN 'mmbtu' THEN 'MMBtu' WHEN 'mw' THEN 'MW' when 'mwd' THEN 'MWD' WHEN 'mwh' THEN 'MWH' WHEN 'mwm' THEN 'MWM' WHEN 'gal' THEN 'Gallon' ELSE isnull(p.unit,'') END 
, unit_plural = CASE isnull(p.unit,'') WHEN 'dth' THEN 'Dth' WHEN 'kwh' THEN 'kWh' WHEN 'kwm' THEN 'kWm' WHEN 'mmbtu' THEN 'MMBtu''s' WHEN 'mw' THEN 'MW' when 'mwd' THEN 'MWD' WHEN 'mwh' THEN 'MWH' WHEN 'mwm' THEN 'MWM'  WHEN 'gal' THEN 'Gallons' ELSE isnull(p.unit,'') END 
, total_qty = convert(double precision, pp.totalquantity)
, priceindex = f.priceindex
, pricediff = convert(double precision, f.pricediff) 
, price = CASE 
            WHEN t.tradetype = 'Phys Power HR' or t.tradetype = 'Phys HR Power Option' and f.priceindex is not null THEN priceindex + '*' + convert(varchar, convert(double precision, factor))
            WHEN t.tradetype = 'Phys Power HR' or t.tradetype = 'Phys HR Power Option' and f.priceindex is null THEN convert(varchar, convert(double precision, f.pricediff))
    WHEN f.priceindex is not null and f.pricediff is null THEN f.priceindex 
            WHEN f.priceindex is not null and isnull(CONVERT(FLOAT, f.pricediff), 0) > 0 THEN f.priceindex + '+' + convert(varchar(max), convert(double precision, f.pricediff))
            WHEN f.priceindex is not null and isnull(CONVERT(FLOAT, f.pricediff), 0) < 0 THEN f.priceindex + '-' + convert(varchar(max), convert(double precision, f.pricediff))
            ELSE convert(varchar(max), convert(double precision, f.pricediff))
          END 
, loadshape = p.loadshape
, lstimeunit = ls.timeunit
, granularity = ls.granularity
, loadshapeHours = 'Hour Ending (HE) ' + CONVERT(VARCHAR,lsq.beghour + 1) + '00 through HE ' + CONVERT(VARCHAR, lsq.endhour) + '00 (' + CONVERT(VARCHAR, lsq.endhour-lsq.beghour-1) +' Hours each day), Monday Through Sunday, including NERC holidays; ' + tz.description
, loadshapeQuantity = convert(double precision, lsq.quantity)
, loadshapeQuantityLoadshape = lsq.loadshape
, loadshapeFlag = CASE
                    WHEN ls.loadshape is not null and ls.granularity = 'LOAD' and lsq.loadshape is null THEN 1
                    WHEN ls.loadshape is not null and ls.granularity = 'PROFILE' THEN 1
                    ELSE 0 END                      
FROM trade t
   INNER JOIN (SELECT *, CASE positiontype WHEN 'BUY' THEN 'PAY' WHEN 'SELL' THEN 'REC' END paystatus from position) p 
        on p.trade = t.trade
   INNER JOIN product pr on p.product = pr.product
   INNER JOIN powerposition pp on p.position = pp.position
   INNER JOIN powerquantity pq on pq.position = pp.position 
        AND pq.posdetail = pp.posdetail 
        AND pq.quantitystatus = 'TRADE'
   INNER JOIN blocktimezone btz on btz.block = p.block and t.timezone = btz.timezone
   LEFT OUTER JOIN fee f on f.dbvalue = p.position
        AND f.dbcolumn = 'POSITION'
        AND f.feemethod = 'COMMODITY PRICE'
        AND f.feemode in ('FIXED', 'VARIABLE')
        AND f.feetype IS NULL
   INNER JOIN counterparty co on co.counterparty = t.company    
   INNER JOIN counterparty cp on cp.counterparty = p.counterparty
   LEFT JOIN loadshape ls on ls.loadshape = p.loadshape
   LEFT JOIN loadshapequantity lsq on lsq.loadshape = ls.loadshape
   LEFT JOIN timezone tz on tz.timezone = t.timezone
 WHERE 1=1
 AND p.positionmode = 'PHYSICAL'
 AND t.collaboration = @collaboration 

【问题讨论】:

    标签: sql-server reporting-services ssrs-2008 ssrs-2008-r2 ssrs-2012


    【解决方案1】:

    您可以使用从第一行开始的递归 CTE:

    ;WITH CTE AS (
            SELECT  TOP 1 *, 1 AS Id
            FROM    #t
            ORDER BY BegDate
            UNION ALL
            SELECT  t.*, c.Id + CASE WHEN t.quanitty = c.quanitty THEN 0 ELSE 1 END 
            FROM    CTE c
                    JOIN #t t ON c.BegDate = DATEADD(MONTH, -1, t.BegDate)
        )
        SELECT  MIN(BegDate) AS BegDate, MAX(EndDate) AS EndDate, MIN(quanitty) AS quanitty
        FROM    CTE
        GROUP BY Id
        ORDER BY Id;
    

    我这样加载示例数据:

    SELECT  CAST(t.BegDate AS DATE) AS BegDate
            , CAST(t.EndDate AS DATE) AS EndDate
            , CAST(t.quanitty AS INT) AS quanitty
    INTO    #t
    FROM    (   VALUES 
                ('1/1/2014','1/31/2014',1),
                ('2/1/2014','2/28/2014',1),
                ('3/1/2014','3/31/2014',2),
                ('4/1/2014','4/30/2014',4),
                ('5/1/2014','5/31/2014',4),
                ('6/1/2014','6/30/2014',4),
                ('7/1/2014','7/31/2014',2),
                ('8/1/2014','8/30/2014',2)
            ) AS t(BegDate,EndDate,quanitty);
    

    【讨论】:

    • 成功了!!你是救生员!我试图投票赞成你的解决方案,但它说我的声誉太低
    • 这仅适用于行始终从该月 1 日开始并在该月最后一天结束并且没有间隔的情况。不确定@user3915771 是否是这种情况
    • 当结果超过 20 行时,这实际上会爆炸
    • @Jack89515 我看不出为什么数字“20”有什么神奇之处会导致它爆炸。 可能有其他问题。你得到什么错误?您可能已达到最大递归限制,因此请尝试在最后的分号前添加“option (maxrecursion 0)”。
    • @Kevin 数字 20 并没有什么神奇之处,我的意思是随着表变大,处理时间由于某种原因呈指数增长。在我的情况下,如果结果小于 10 行,我会得到一个即时查询结果,在 21 行时,sql server 返回时间是 7 秒,之后的任何行都需要永远,耗尽所有服务器处理能力,直到我杀死进程
    【解决方案2】:

    检查一下

    select  min(BegDate) as BegDate, max(EndDate) as EndDate, min(quanitty) as quanitty
    from
    (
        select *, row_number() over(partition by quanitty order by quanitty)  p_rno
        ,row_number() over(order by BegDate)  rno 
        --,row_number() over(partition by quanitty order by quanitty)-
        -- row_number() over(order by BegDate)  rno 
        from #t
    ) t
    group by (p_rno-rno)
    order by BegDate
    

    【讨论】:

      猜你喜欢
      • 2017-01-24
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 2021-08-19
      • 2012-05-12
      • 2016-01-20
      • 2022-07-17
      相关资源
      最近更新 更多