我很少在T-SQL报告查询中使用while循环。事实上,这可能是我们整个报告系统中唯一的看法。因此,我决定检查是否有人有更好的方法来解决以下问题。
您有一份报告,您必须查询两年的交易。其中一列是日历季度排名。我将在一分钟内解释这是什么。
每个日历日期都有一个财务季度。我相信这是普遍的,但从美国的角度来看,1月1日到3月30日是一年的第1季度,4月1日到6月30日是一年的第2季度,依此类推。
我想要做的是从给定的日期范围中取出所有季度并按数字排名。这意味着如果我的报告从2012年4月1日开始并持续到2014年3月30日(八个季度),那么2012年4月1日到2012年6月30日之间的日期将被排列为第1季度(对于我的报告)。
2012年7月1日的日期将被列为第2季度。
2014年3月30日的交易日期将落入我的报告的第8季度。
为了解决这个问题,我使用了一个while循环来旋转报告范围中的日期,并在季度增加1时指定数字季度排名(日期从2012年6月30日到2012年7月1日,例如)。
这是代码......
declare @tv_transactions table(recnum int identity(1,1) primary key, item varchar(50), amt money, txndate datetime)
insert into @tv_transactions(item, amt, txndate)values('iPod Shuffle', 130, '2012-04-03')
insert into @tv_transactions(item, amt, txndate)values('xBox One S', 299, '2012-05-12')
insert into @tv_transactions(item, amt, txndate)values('iMac Pro', 4999, '2012-07-23')
insert into @tv_transactions(item, amt, txndate)values('Flash Stick', 4.50, '2012-08-01')
insert into @tv_transactions(item, amt, txndate)values('Pencils', 3.67, '2012-10-23')
insert into @tv_transactions(item, amt, txndate)values('Markers', 4.99, '2012-11-20')
insert into @tv_transactions(item, amt, txndate)values('Windex', 1.99, '2013-01-23')
insert into @tv_transactions(item, amt, txndate)values('echo dot', 49, '2013-02-14')
insert into @tv_transactions(item, amt, txndate)values('Eggs', 3.99, '2013-04-12')
insert into @tv_transactions(item, amt, txndate)values('Strawberries', 2.99, '2013-06-23')
insert into @tv_transactions(item, amt, txndate)values('Portable Generator', 880, '2013-08-12')
insert into @tv_transactions(item, amt, txndate)values('Mattress Pad', 103.99, '2013-09-03')
insert into @tv_transactions(item, amt, txndate)values('Power Drill', 49.99, '2013-10-11')
insert into @tv_transactions(item, amt, txndate)values('GT Road GT', 14.77, '2013-11-20')
insert into @tv_transactions(item, amt, txndate)values('QFit Bluetoot Speaker', 25.99, '2014-01-31')
insert into @tv_transactions(item, amt, txndate)values('Toilet Night Light', 8.99, '2014-02-23')
insert into @tv_transactions(item, amt, txndate)values('BS-MALL Makeup Brushes', 6.29, '2014-03-14')
declare @startdate datetime
, @enddate datetime
, @datecount datetime
, @year int
, @quarter int
, @quartercount int
declare @tv_quarters table(quarternum int primary key, year int, quarter int)
/****************************************************************************
* Inatialize Variables *
****************************************************************************/
select @startdate = '2012-04-01'
, @enddate = '2014-03-30'
, @datecount = null
select @datecount = @startdate
select @year = year(@datecount)
, @quarter = datepart(quarter, @datecount)
, @quartercount = 1
insert into @tv_quarters(quarternum, year, quarter) values(@quartercount, @year, @quarter)
select @datecount = dateadd(day, 1, @datecount)
while(@datecount <= @enddate)
begin
select @year = null
, @quarter = null
select @year = year
, @quarter = quarter
from @tv_quarters
where quarternum = @quartercount
if(year(@datecount) <> @year or datepart(quarter, @datecount) <> @quarter)
Begin
select @quartercount = @quartercount + 1
insert into @tv_quarters(quarternum, year, quarter)
select @quartercount, year(@datecount), datepart(quarter, @datecount)
End
select @datecount = dateadd(day, 1, @datecount)
end
select t.item, t.amt, t.txndate, q.quarternum
from @tv_transactions t
inner join @tv_quarters q on q.year = year(t.txndate) and q.quarter = datepart(quarter, t.txndate)
order by q.quarternum asc
有没有更好的方法来解决这个问题?有没有办法避免使用while循环?
我的公司目前正在使用SQL Server 2005(嘿嘿嘿嘿嘲笑我),但我们正在迁移到SQL 2016,所以我对所有建议持开放态度。
谢谢
答案 0 :(得分:3)
更新回答:
如果您希望const options = {
tooltips: {
enabled: false,
custom: (tooltip) => {
// Retrieving valuable props from tooltip (caretX, caretY)
// and creating custom tooltip that is positioned
// on top of a bar
}
}
// other options
}
const chart = new Chart(ctx, {
type: 'bar',
data,
options
})
只代表该季度的序数与quarternum
相比,那么您可以使用@startdate
:
datediff()
rextester演示:http://rextester.com/GBO47881
返回:(删除了两行以显示间隙)
declare @startdate datetime
, @enddate datetime
select @startdate = '2012-04-01'
, @enddate = '2014-04-01';
select
t.item
, t.amt
, t.txndate
, quarternum = datediff(quarter, @startdate, t.txndate)+1
from @tv_transactions t
order by quarternum asc
您可以使用dense_rank()
introduced in SQL Server 2005,并且因为您的季度与日历年一致,您可以使用+------------------------+-----------+------------+------------+
| item | amt | txndate | quarternum |
+------------------------+-----------+------------+------------+
| iMac Pro | 4999,0000 | 2012-07-23 | 2 |
| Flash Stick | 4,5000 | 2012-08-01 | 2 |
| Pencils | 3,6700 | 2012-10-23 | 3 |
| Markers | 4,9900 | 2012-11-20 | 3 |
| Windex | 1,9900 | 2013-01-23 | 4 |
| echo dot | 49,0000 | 2013-02-14 | 4 |
| Eggs | 3,9900 | 2013-04-12 | 5 |
| Strawberries | 2,9900 | 2013-06-23 | 5 |
| Portable Generator | 880,0000 | 2013-08-12 | 6 |
| Mattress Pad | 103,9900 | 2013-09-03 | 6 |
| Power Drill | 49,9900 | 2013-10-11 | 7 |
| GT Road GT | 14,7700 | 2013-11-20 | 7 |
| QFit Bluetoot Speaker | 25,9900 | 2014-01-31 | 8 |
| Toilet Night Light | 8,9900 | 2014-02-23 | 8 |
| BS-MALL Makeup Brushes | 6,2900 | 2014-03-14 | 8 |
+------------------------+-----------+------------+------------+
和year()
而无需对其进行任何修改排名顺序:
datepart(quarter,...)
rextester演示:http://rextester.com/YMPVMQ59269
返回:
select
t.item
, t.amt
, t.txndate
, quarternum = dense_rank() over (order by year(t.txndate), datepart(quarter,t.txndate))
from @tv_transactions t
order by quarternum asc
答案 1 :(得分:1)
您可以使用带有递归CTE(SQL Server 2005 +)的可自定义解决方案:
DECLARE @startdate datetime = '2012-04-01',
@enddate datetime = '2014-04-01';
WITH dates AS (
SELECT 1 AS quarternum, @startdate AS startDate, DATEADD(mm, 3, @startdate) AS endDate
UNION ALL
SELECT t.quarternum + 1, t.endDate, DATEADD(mm, 3, t.endDate) FROM dates t WHERE DATEADD(mm, 3, t.endDate) <= @enddate
)
SELECT tt.item, tt.amt, tt.txndate, d.quarternum
FROM @tv_transactions tt
INNER JOIN dates d ON d.startDate <= tt.txndate AND d.endDate > tt.txndate;
输出:
item amt txndate quarternum
---------------------------------- ----------- -----------
iPod Shuffle 130,00 2012-04-03 1
xBox One S 299,00 2012-05-12 1
iMac Pro 4999,00 2012-07-23 2
Flash Stick 4,50 2012-08-01 2
Pencils 3,67 2012-10-23 3
Markers 4,99 2012-11-20 3
Windex 1,99 2013-01-23 4
echo dot 49,00 2013-02-14 4
Eggs 3,99 2013-04-12 5
Strawberries 2,99 2013-06-23 5
Portable Generator 880,00 2013-08-12 6
Mattress Pad 103,99 2013-09-03 6
Power Drill 49,99 2013-10-11 7
GT Road GT 14,77 2013-11-20 7
QFit Bluetoot Speaker 25,99 2014-01-31 8
Toilet Night Light 8,99 2014-02-23 8
BS-MALL Makeup Brushes 6,29 2014-03-14 8
请注意@enddate
已更改。