在sql函数中添加日期

时间:2014-10-23 17:53:50

标签: sql sql-server-2008 date datetime dateadd

我在sql中有一个查询,我用C#编写。查询的作用是什么,计算类似于我输入两列date和no的东西。球如

Date        No. of balls
21/11/2013  2
22/11/2013  3
23/11/2013  4
24/11/2013  5
25/11/2013  2
26/11/2013  5
27/11/2013  4
28/11/2013  3
29/11/2013  9
30/11/2013  8
01/12/2013  7
02/12/2013  4
03/12/2013  5
04/12/2013  6
05/12/2013  2
06/12/2013  0
07/12/2013  1

输出应该看起来像

newdate                no. of balls
21/11/2013 -27/11/2013  25
28/11/2013-04/12/2013   42
05/12/2013-07/12/2013   3

即。日期是7天的间隔,如2013年11月21日至2013年11月27日,然后是下一个7 28/11 / 2013-04 / 12/2013等等,但它应该将enddate视为数据库日期的结束(如第3行所示)。 我想在sql中使用create function functioname(例如函数名作为interval)创建一个函数,该函数应该返回输出的日期列,以便我可以在用c#编写的sql查询中使用该函数(dbo.interval) 如

string query = @" select dbo.interval([Date]) newdate,
                  IsNull(ROUND(sum(No. of balls),2),0) [no. of balls] 
                  from stock
                   Where  date between Convert(Datetime,'" + Fromdate + "',103) and      Convert(Datetime,'" + Todate + "',103)
 Group By dbo.interval([date])";

PS:股票是两列日期和否的表格。球和+ Fromdate +和+ Todate +下拉显示在grid.it基本上是由用户提供的日期的上限和下限,以了解这两个日期之间的信息(在这种情况下,上限和下限的日期是分别于2013年11月21日和2013年7月12日)。因此输出文件看起来像

newdate no。的球 21/11/2013 -27/11/2013 25 28/11 / 2013-04 / 12/2013 42 05/12 / 2013-07 / 12/2013 3

我曾尝试在sql中使用RecursiveCTE但它没有多大帮助,因为它只提供一个临时输出。

2 个答案:

答案 0 :(得分:0)

解决问题的最简单方法是逐个查询使用ROLLUP(http://technet.microsoft.com/en-us/library/bb522495(v=sql.105).aspx

这是SQL小提琴(http://sqlfiddle.com/#!3/3ce09/19

日期定义:

create table test (
    Id  INT IDENTITY(1,1),
    date  DateTime,
    balls  int );
insert into test(date, balls) values('11/21/2013',  2);
insert into test(date, balls) values('11/22/2013',  3);
insert into test(date, balls) values('11/23/2013',  4);
insert into test(date, balls) values('11/24/2013',  5);
insert into test(date, balls) values('11/25/2013',  2);
insert into test(date, balls) values('11/26/2013',  5);
insert into test(date, balls) values('11/27/2013',  4);
insert into test(date, balls) values('11/28/2013',  3);
insert into test(date, balls) values('11/29/2013',  9);
insert into test(date, balls) values('11/30/2013',  8);
insert into test(date, balls) values('12/01/2013',  7);
insert into test(date, balls) values('12/02/2013',  4);
insert into test(date, balls) values('12/03/2013',  5);
insert into test(date, balls) values('12/04/2013',  6);
insert into test(date, balls) values('12/05/2013',  2);
insert into test(date, balls) values('12/06/2013',  0);
insert into test(date, balls) values('12/07/2013',  1);

实际查询:

select 
  label, 
  balls 
  from ( 
     SELECT  
       (DATEDIFF(d , '11/21/2013' , date) / 7) as week, 
       ((DATEDIFF(d , '11/21/2013' , date) / 7) + 1) as week1, 
       LEFT(CONVERT(VARCHAR, (DateAdd(d, (DATEDIFF(d , '11/21/2013' , date) / 7)*7, '11/21/2013')), 120), 10) +    ' - ' +  
       LEFT(CONVERT(VARCHAR, (DateAdd(d, ((DATEDIFF(d , '11/21/2013' , date) / 7) + 1)*7 - 1, '11/21/2013')), 120), 10) as label, 
       SUM(Balls) as balls 
      FROM test 
      GROUP BY rollup((DATEDIFF(d , '11/21/2013' , date) / 7))   
  ) as t 
  where t.label is not null

结果:

LABEL                       BALLS
2013-11-21 - 2013-11-27     25
2013-11-28 - 2013-12-04     42
2013-12-05 - 2013-12-11     3

答案 1 :(得分:0)

我认为你根本不需要使用某个功能。我拿了Maksym的测试数据,整理了一下并编写了一个查询,它可以带回你需要的数据而不需要调用UDF:

DECLARE @Test TABLE (
    Id  INT IDENTITY(1,1),
    [Date] DATE,
    Balls  INT);
INSERT INTO @Test([Date], Balls) VALUES('20131121',  2);
INSERT INTO @Test([Date], Balls) VALUES('20131122',  3);
INSERT INTO @Test([Date], Balls) VALUES('20131123',  4);
INSERT INTO @Test([Date], Balls) VALUES('20131124',  5);
INSERT INTO @Test([Date], Balls) VALUES('20131125',  2);
INSERT INTO @Test([Date], Balls) VALUES('20131126',  5);
INSERT INTO @Test([Date], Balls) VALUES('20131127',  4);
INSERT INTO @Test([Date], Balls) VALUES('20131128',  3);
INSERT INTO @Test([Date], Balls) VALUES('20131129',  9);
INSERT INTO @Test([Date], Balls) VALUES('20131130',  8);
INSERT INTO @Test([Date], Balls) VALUES('20131201',  7);
INSERT INTO @Test([Date], Balls) VALUES('20131202',  4);
INSERT INTO @Test([Date], Balls) VALUES('20131203',  5);
INSERT INTO @Test([Date], Balls) VALUES('20131204',  6);
INSERT INTO @Test([Date], Balls) VALUES('20131205',  2);
INSERT INTO @Test([Date], Balls) VALUES('20131206',  0);
INSERT INTO @Test([Date], Balls) VALUES('20131207',  1);
DECLARE @StartDate DATE = '20131121';
DECLARE @EndDate DATE = '20131207';

WITH StartDates AS (
    SELECT 
        CASE WHEN DATEDIFF(DAY, @StartDate, [Date]) % 7 = 0 THEN [Date] END AS StartDate
    FROM
        @Test),
EndDates AS (
    SELECT
        StartDate,
        CASE WHEN DATEADD(DAY, 6, StartDate) > @EndDate THEN @EndDate ELSE DATEADD(DAY, 6, StartDate) END AS EndDate
    FROM
        StartDates)
SELECT 
    ed.StartDate,
    ed.EndDate,
    CONVERT(VARCHAR(12), ed.StartDate, 103) + ' - ' + CONVERT(VARCHAR(12), ed.EndDate, 103) AS NewDate,
    ISNULL(ROUND(SUM(Balls), 2), 0) [Balls] 
FROM 
    @Test t
    INNER JOIN EndDates ed ON DATEDIFF(DAY, ed.StartDate, t.[Date]) BETWEEN 0 AND 7 AND DATEDIFF(DAY, t.[Date], ed.EndDate) BETWEEN 0 AND 7
WHERE  
    [Date] BETWEEN @StartDate AND @EndDate
GROUP BY 
    ed.StartDate,
    ed.EndDate,
    CONVERT(VARCHAR(12), ed.StartDate, 103) + ' - ' + CONVERT(VARCHAR(12), ed.EndDate, 103)
ORDER BY 
    ed.StartDate;

这给出了以下结果:

StartDate   EndDate     NewDate                 Balls
2013-11-21  2013-11-27  21/11/2013 - 27/11/2013 25
2013-11-28  2013-12-04  28/11/2013 - 04/12/2013 42
2013-12-05  2013-12-07  05/12/2013 - 07/12/2013 3

如果您将我的查询转换为针对[Stock]表的工作,那么您应该能够将其嵌入到.NET解决方案中,将@StartDate和@EndDate替换为用户提供的值,用[Stock替换@Test ]并相应地修改列名?