根据记录值转换为行数

时间:2016-01-02 06:47:22

标签: sql-server tsql ssis

我有一个场景,我目前被困在

表abc有金额,fromdate,todate,numberofquarters(从todate fromdate计算)

示例:

amount  fromdate    todate      numberofquarters

140    01/01/2011   06/01/2014   14

我必须按比例按季度制作上表 即14条记录

amount  fromdate    todate      
10     01/01/2011   03/31/2011   
10     01/04/2011   06/30/2011   
10     01/07/2011   09/31/2011   
10     01/10/2011   12/31/2011  
10     01/01/2012   03/31/2012   
10     01/04/2012   06/30/2012   
10     01/07/2012   09/31/2012   
10     01/10/2012   12/31/2012  
10     01/01/2013   03/31/2013   
...and so on

请建议我在不使用游标的情况下实现结果的任何方法。

2 个答案:

答案 0 :(得分:0)

您可以通过拥有永久日期或数字表(每个日期或数字一行)或动态构建它来执行此类操作,如下所示:

;WITH lv0 AS (SELECT 0 g UNION ALL SELECT 0)
    ,lv1 AS (SELECT 0 g FROM lv0 a CROSS JOIN lv0 b) -- 4
    ,lv2 AS (SELECT 0 g FROM lv1 a CROSS JOIN lv1 b) -- 16
    ,lv3 AS (SELECT 0 g FROM lv2 a CROSS JOIN lv2 b) -- 256
    ,Tally (n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM lv3)
SELECT 
  abc.amount / numberofquarters, 
  dateadd(month, (n-1)*3, abc.fromdate) as fromdate,
  dateadd(day, -1, dateadd(month, n*3, abc.fromdate)) as todate
FROM 
  Tally T 
  join abc on abc.numberofquarters >= T.N
Order by fromdate

这将创建一个包含256行的表,如果您需要更多的季度,那么只需在CTE中添加一个类似的连接。然后将其与abc连接,以便该数字用于将几个月添加到开始日期。

SQL Fiddle

中的示例

答案 1 :(得分:0)

假设所需的输出:
  金额=金额列的总和,
  fromdate = fomdate列的最小值,
  todate = todate列的最小值   宿舍不会跨越多年。

SELECT
    amount,
    fromdate,
    todate,
    COUNT(DISTINCT CASE 
       WHEN DATEPART(DAY, fromdate) > DATEPART(DAY, todate)
       THEN DATEDIFF(MONTH, fromdate, todate) - 1
       ELSE DATEDIFF(MONTH, fromdate, todate)
    END % 3 + YEAR(fromdate)) quarters
FROM (
    SELECT 
      SUM(amount) amount,
      MIN(fromdate) fromdate, 
      MAX(todate) todate
      FROM abc
 ) subq

应该给你想要的结果