简体   繁体   English

在没有循环的情况下在SQL中创建年/季度表

[英]Create a year/quarter table in SQL without a loop

I have a start year and an end year, say 2017 and 2019 for example. 我有一个开始年份和结束年份,例如2017年和2019年。

I'd like to create a table with columns year and quarter (eg, 1, 2, 3, 4) between my stated startYear and endYear, and have quarter for the final, endYear , to stop at 2 (it's always forward looking). 我想在我声明的startYear和endYear之间创建一个包含年份季度 (例如1,2,3,4)列的表,并且在最终的endYear中有一个季度 ,在2处停止(它始终向前看) 。

Sample desired output below. 下面的样本输出。

year    quarter
2017    1
2017    2
2017    3
2017    4
2018    1
2018    2
2018    3
2018    4
2019    1
2019    2

Seems like it should be simple, nothing occurs to me except somewhat clunky methods relying on a loop or UNION or simply inserting values manually into the table. 看起来它应该很简单,除了有些笨重的方法依赖于循环或UNION或只是手动将值插入表中,没有任何事情发生在我身上。

Just another option... an ad-hoc tally table in concert with a Cross Join 另一种选择......与Cross Join一致的临时计数表

Example

Declare @Y1 int = 2017
Declare @Y2 int = 2019

Select *
 From ( Select Top (@Y2-@Y1+1) Year=@Y1-1+Row_Number() Over (Order By (Select NULL)) From master..spt_values n1 ) A
 Cross Join (values (1),(2),(3),(4)) B([Quarter])

Returns 返回

Year    Quarter
2017    1
2017    2
2017    3
2017    4
2018    1
2018    2
2018    3
2018    4
2019    1
2019    2
2019    3
2019    4

Use a recursive CTE: 使用递归CTE:

with yq as (
      select 2017 as yyyy, 1 as qq
      union all
      select (case when qq = 4 then yyyy + 1 else yyyy end), 
              (case when qq = 4 then 1 else qq + 1 end)
      from yq
      where yyyy < 2019 or yyyy = 2019 and qq < 2
     )
select *
from yq;

If the table will have more than 100 rows, you will also need option (maxrecursion 0) . 如果表的行数超过100行,则还需要option (maxrecursion 0)

Here is a db<>fiddle. 是一个db <>小提琴。

This solution is very similar to the one by John, but it doesn't depend on a system table. 此解决方案与John的解决方案非常相似,但它不依赖于系统表。

Declare @Y1 int = 2017;
Declare @Y2 int = 2019;

WITH 
E(n) AS(
    SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
    SELECT a.n FROM E a, E b
),
E4(n) AS(
    SELECT a.n FROM E2 a, E2 b
),
cteYears([Year]) AS(
    SELECT TOP (@Y2-@Y1+1)
            ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + @Y1 - 1 AS [Year]
    FROM E4
)
SELECT [Year], [Quarter]
FROM cteYears
CROSS JOIN (VALUES (1),(2),(3),(4)) Q([Quarter]);

Let me to propose a recursve query for you: 让我为您提出一个递归查询:

 WITH prepare AS ( SELECT tbl.year FROM (VALUES (2017) ) AS tbl(year) -- for example, start year is 2k17 UNION ALL SELECT year + 1 FROM prepare WHERE year < 2030 -- and last year is 2030 ) SELECT year, quarter FROM prepare CROSS JOIN ( VALUES (1), (2), (3), (4) ) AS tbl (quarter) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM