从表中每月获取日期

时间:2014-12-16 14:54:30

标签: sql-server tsql

你能解决问题吗

我有桌子价格表,每日价格从2010年12月31日到今天为止。该表包含每日价格



2009-12-31 00:00:00.000	1.0020945351
2010-01-01 00:00:00.000	1.0021009300
2010-01-04 00:00:00.000	1.0021910181
2010-01-05 00:00:00.000	1.0022005986
2010-01-06 00:00:00.000	1.0022428696
2010-01-07 00:00:00.000	1.0022647147
2010-01-08 00:00:00.000	1.0022842726
2010-01-11 00:00:00.000	1.0023374302
2010-01-12 00:00:00.000	1.0023465374
2010-01-13 00:00:00.000	1.0023638081
2010-01-14 00:00:00.000	1.0023856533
2010-01-00 00:00:00.000	1.0024083955
2010-01-18 00:00:00.000	1.0024779677
2010-01-19 00:00:00.000	1.0025020553
2010-01-20 00:00:00.000	1.002521135
2010-01-21 00:00:00.000	1.0025420688
2010-01-22 00:00:00.000	1.0025593397
2010-01-25 00:00:00.000	1.0026180146
2010-01-26 00:00:00.000	1.002637573
2010-01-27 00:00:00.000	1.0026648447
2010-01-28 00:00:00.000	1.0026957934
2010-01-29 00:00:00.000	1.0027267421
2010-02-01 00:00:00.000	1.0028195885
2010-02-02 00:00:00.000	1.0028573523
2010-02-03 00:00:00.000	1.0028964611
2010-02-04 00:00:00.000	1.00293557
2010-02-05 00:00:00.000	1.002973334
2010-02-08 00:00:00.000	1.0030879717
2010-02-09 00:00:00.000	1.0031279777
2010-02-10 00:00:00.000	1.003171166
2010-02-11 00:00:00.000	1.0032007452
2010-02-12 00:00:00.000	1.0032575895
2010-02-00 00:00:00.000	1.0033749191
2010-02-1 00:00:00.000	1.0034140292
2010-02-17 00:00:00.000	1.003452691
2010-02-18 00:00:00.000	1.0034918013
2010-02-19 00:00:00.000	1.0035395633
2010-02-22 00:00:00.000	1.0036664439
2010-02-23 00:00:00.000	1.0037042097
2010-02-24 00:00:00.000	1.0037510759
2010-02-25 00:00:00.000	1.0038001834
2010-02-26 00:00:00.000	1.003850077




我需要编写一个查询来获取索引 (当月的最后一天/上个月的最后一天) - 1 * 100.所以输出就像这样



31-Jan-10	0.01%
28-Feb-10	0.02%
31-Mar-10	0.00%




以下是我想到的解决方案之一,但请分享最好的想法来实现这个问题

将所有月份的最后一天的值提取到临时表中,然后按日期排序,以便它们减去并将值放入另一个临时表中

期待您的帮助。

3 个答案:

答案 0 :(得分:1)

试试这个......

DECLARE @StartDate  DATETIME = '2010-01-01',
    @EndDate    DATETIME = GETDATE();

WITH data AS (
SELECT 1 AS i, CONVERT(DATETIME, NULL) AS StartDate, DATEADD(MONTH, 0, @StartDate) - 1 AS EndDate
UNION ALL
SELECT i + 1, data.EndDate, DATEADD(MONTH, i, @StartDate) - 1 AS EndDate
FROM data
WHERE DATEADD(MONTH, i, @StartDate) - 1 < @EndDate
) 

SELECT (
((SELECT TOP 1 Rate FROM RateTable WHERE Date <= data.EndDate ORDER BY Date DESC) /
 (SELECT TOP 1 Rate FROM RateTable WHERE Date <= data.StartDate ORDER BY Date DESC)- 1) * 100)
FROM DATA                                             -- parenthesis were causing issues
WHERE data.StartDate IS NOT NULL
OPTION (MAXRECURSION 10000);

您需要更换

(SELECT Rate FROM RateTable WHERE Date = data.StartDate)
and
(SELECT Rate FROM RateTable WHERE Date = data.EndDate)

使用费率表的值。因为你没有在你的问题中提到列名和表名。

rwking表示,费率表中可能存在导致问题的空白。 我修改了子查询,以便在开始和结束日期之前或最接近第一个费率。

希望有所帮助

答案 1 :(得分:1)

您可以使用SQL2012中引入的LAG函数使其更容易:

WITH DataWithOrder AS
(
    SELECT DateField, PriceField,
        ROW_NUMBER() OVER(PARTITION BY YEAR(DateField), Month(DateField) ORDER BY DateField DESC) AS Pos
    FROM PriceTable
)
SELECT
  DateField,
  PriceField,
  LAG(PriceField) OVER(ORDER BY DateField) AS PriceLastMonth,
  ((PriceField / LAG(PriceField) OVER(ORDER BY DateField)) - 1) * 100 AS PCIncrease
FROM DataWithOrder
WHERE Pos = 1
ORDER BY DateField

答案 2 :(得分:0)

我采取了与另一个人截然不同的方法。如果每日数据确实代表每个月的每一天,他会更优雅并且会更好。但是,如果您的样本数据代表天数存在差距,则可以尝试以下代码。

with cte as (select mydate
                  , price
                  , ROW_NUMBER() over(partition by YEAR(mydate), MONTH(mydate) 
                                      order by day(mydate) desc) row_n
             from #temp)
select mydate, price, ROW_NUMBER() over(order by mydate desc) row_num
into #temp2
from cte
where row_n = 1          

alter table #temp2
add idx float

declare @counter int = 1
while @counter < (select MAX(row_num)+1 from #temp2)

begin
update t2
set t2.idx = ((t2.price/t3.price)-1)*100
from #temp2 t2 left join 
     #temp2 t3 on 1 = 1 
where t2.row_num = @counter and t3.row_num = @counter + 1

set @counter = @counter + 1
end

select mydate, idx
from #temp2

正如另一张海报所提到的,你没有提供列名或表名。我的过程是将您的数据插入名为[#temp]的表中,列名为[mydate]和[price]。

此外,您提供的数据样本包含两个无效日期,我更改为任意日期只是为了让代码运行。 (2010-01-00和2010-02-00)