SQL Server:从每日重复值获取日期范围

时间:2018-11-05 22:50:20

标签: sql-server sql-server-2008 sql-server-2012

在SQL Server中,我有一个表,该表具有作为每日记录存储的货币汇率,该表如下所示:

CREATE TABLE `crt` 
(
    `cur_code_fm` char(3) NOT NULL,
    `cur_code_to` char(3) NOT NULL,
    `crt_date` date NOT NULL,
    `crt_rate` decimal(16,8) NOT NULL,
    `ct_md` char(1) NOT NULL
);

交换通常在几周甚至几个月的时间内保持不变。

Record sample

'USD', 'CRC', '2017-12-24', '550.00000000', 'M'
'USD', 'CRC', '2017-12-25', '550.00000000', 'M'
'USD', 'CRC', '2017-12-26', '550.00000000', 'M'
'USD', 'CRC', '2017-12-27', '550.00000000', 'M'
'USD', 'CRC', '2017-12-28', '550.00000000', 'M'
'USD', 'CRC', '2017-12-29', '550.00000000', 'M'
'USD', 'CRC', '2017-12-30', '550.00000000', 'M'
'USD', 'CRC', '2017-12-31', '550.00000000', 'M'
'USD', 'CRC', '2018-01-01', '565.00000000', 'M'
'USD', 'CRC', '2018-01-02', '565.00000000', 'M'
'USD', 'CRC', '2018-01-03', '565.00000000', 'M'
'USD', 'CRC', '2018-01-04', '565.00000000', 'M'
'USD', 'CRC', '2018-01-05', '565.00000000', 'M'
'USD', 'CRC', '2018-01-06', '565.00000000', 'M'
'USD', 'CRC', '2018-01-07', '565.00000000', 'M'
'USD', 'CRC', '2018-01-08', '565.00000000', 'M'

我想将其合并为这样的日期范围:

Desired result

'89', 'USD', 'CRC', '2013-12-01', '2013-12-31', '494.00000000', 'M'
'90', 'USD', 'CRC', '2014-01-01', '2014-01-31', '498.00000000', 'M'
'91', 'USD', 'CRC', '2014-02-01', '2014-02-28', '522.00000000', 'M'
'92', 'USD', 'CRC', '2014-03-01', '2014-03-31', '542.00000000', 'M'
'93', 'USD', 'CRC', '2014-04-01', '2014-04-30', '540.00000000', 'M'
'94', 'USD', 'CRC', '2014-05-01', '2014-06-30', '545.00000000', 'M'
'95', 'USD', 'CRC', '2014-07-01', '2014-07-31', '533.00000000', 'M'
'96', 'USD', 'CRC', '2014-08-01', '2014-12-31', '534.00000000', 'M'
'97', 'USD', 'CRC', '2016-01-01', '2017-06-30', '500.00000000', 'M'
'98', 'USD', 'CRC', '2017-07-01', '2017-12-31', '550.00000000', 'M'
'99', 'USD', 'CRC', '2018-01-01', '2018-06-30', '565.00000000', 'M'
'100', 'USD', 'EUR', '2010-01-01', '2010-05-31', '1.45000000', 'D'
'101', 'USD', 'EUR', '2013-07-01', '2013-07-31', '0.76400000', 'D'
'102', 'USD', 'SFR', '2010-01-01', '2010-06-30', '1.15000000', 'M'
'103', 'USD', 'SFR', '2015-01-01', '2015-12-31', '1.01500000', 'M'
'104', 'USD', 'USD', '2004-01-01', '2029-12-31', '1.00000000', 'M'

在MySQL中,我可以通过使用以下变量来跟踪记录之间的汇率和货币变化来轻松实现此目的:

SET @set := 0;
SET @pfm := '' Collate utf8_unicode_ci;
SET @pto := '' Collate utf8_unicode_ci;
SET @prt := 0;

SELECT
    grate.serie,
    grate.cur_code_fm AS Min_cur_code_fm,
    grate.cur_code_to,
    MIN(grate.crt_date) AS datefrom,
    MAX(grate.crt_date) AS dateto,
    grate.crt_rate,
    grate.ct_md
FROM
    (SELECT
         CASE
            WHEN (@pfm != snatch.crt.cur_code_fm) OR (@pto != snatch.crt.cur_code_to) OR (@prt != snatch.crt.crt_rate)
               THEN @set := @set + 1
               ELSE @set
         END AS serie,
         crt.cur_code_fm,
         crt.cur_code_to,
         crt.crt_date,
         crt.crt_rate,
         crt.ct_md,
         @pfm := crt.cur_code_fm,
         @pto := crt.cur_code_to,
         @prt := crt.crt_rate
     FROM
         crt
     ORDER BY
         crt.cur_code_fm, crt.cur_code_to, crt.crt_date) grate
GROUP BY
    grate.serie, grate.cur_code_fm,
    grate.cur_code_to, grate.crt_rate, grate.ct_md;

如何在SQL Server 2008+中实现相同的目标?

谢谢。

使用ZLK的评论解决了该问题:

SELECT
  grate.serie,
  grate.CUR_CODE_FM,
  grate.CUR_CODE_TO,
  Min(grate.CRT_DATE) AS Min_CRT_DATE,
  Max(grate.CRT_DATE) AS Max_CRT_DATE,
  grate.CRT_RATE,
  grate.CT_MD
FROM
  (SELECT
      serie = Row_Number() OVER (PARTITION BY CRT.CUR_CODE_FM, CRT.CUR_CODE_TO,
      CRT.CT_MD ORDER BY CRT.CRT_DATE) - Row_Number() OVER (PARTITION BY
      CRT.CUR_CODE_FM, CRT.CUR_CODE_TO, CRT.CT_MD,
      CRT.CRT_RATE ORDER BY CRT.CRT_DATE),
      CRT.CUR_CODE_FM,
      CRT.CUR_CODE_TO,
      CRT.CRT_DATE,
      CRT.CRT_RATE,
      CRT.CT_MD
    FROM
      CRT) grate
GROUP BY
  grate.serie,
  grate.CUR_CODE_FM,
  grate.CUR_CODE_TO,
  grate.CRT_RATE,
  grate.CT_MD
ORDER BY
  grate.CUR_CODE_FM,
  grate.CUR_CODE_TO,
  Min_CRT_DATE

非常感谢您。

1 个答案:

答案 0 :(得分:0)

我不确定您是如何根据预期结果得出费率的。但我想剩下的就是他们了。您可以从这里开始:

DECLARE 
    @crt TABLE (
      cur_code_fm char(3) NOT NULL,
      cur_code_to char(3) NOT NULL,
      crt_date date NOT NULL,
      crt_rate decimal(16,8) NOT NULL,
      ct_md char(1) NOT NULL        
    )

INSERT INTO @crt VALUES 
('USD', 'CRC', '2017-12-24', 550.00000000, 'M'),
('USD', 'CRC', '2017-12-25', 550.00000000, 'M'),
('USD', 'CRC', '2017-12-26', 550.00000000, 'M'),
('USD', 'CRC', '2017-12-27', 550.00000000, 'M'),
('USD', 'CRC', '2017-12-28', 550.00000000, 'M'),
('USD', 'CRC', '2017-12-29', 550.00000000, 'M'),
('USD', 'CRC', '2017-12-30', 550.00000000, 'M'),
('USD', 'CRC', '2017-12-31', 550.00000000, 'M'),
('USD', 'CRC', '2018-01-01', 565.00000000, 'M'),
('USD', 'CRC', '2018-01-02', 565.00000000, 'M'),
('USD', 'CRC', '2018-01-03', 565.00000000, 'M'),
('USD', 'CRC', '2018-01-04', 565.00000000, 'M'),
('USD', 'CRC', '2018-01-05', 565.00000000, 'M'),
('USD', 'CRC', '2018-01-06', 565.00000000, 'M'),
('USD', 'CRC', '2018-01-07', 565.00000000, 'M'),
('USD', 'CRC', '2018-01-08', 565.00000000, 'M')



SELECT ROW_NUMBER() OVER(ORDER BY crt_date_fm) RN, *
FROM (
    SELECT 
        cur_code_fm
    ,   cur_code_to
    ,   crt_date_fm
    ,   crt_date_to
    ,   MAX(crt_rate) crt_rate
    ,   ct_md 
    ,   reaccuring
    FROM (
        SELECT
            cur_code_fm
        ,   cur_code_to
        ,   DATEADD(DAY, - DAY(crt_date) + 1 , crt_date) crt_date_fm
        ,   DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(DAY, - DAY(crt_date) + 1 , crt_date) ) ) crt_date_to
        ,   COUNT(cur_code_fm) OVER(PARTITION BY cur_code_fm, YEAR(crt_date), MONTH(crt_date)) recurring 
        ,   crt_rate
        ,   ct_md 
        FROM @crt
    ) D
    GROUP BY 
        cur_code_fm
    ,   cur_code_to
    ,   crt_date_fm
    ,   crt_date_to
    ,   ct_md 
    ,   reaccuring
) E 

重复计数同一个月内重复利率的次数。

如果您可以澄清您的问题,并说明您在费率上使用的是什么逻辑,我可能会将答案更新为一个完整的答案。