我在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但它没有多大帮助,因为它只提供一个临时输出。
答案 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 ]并相应地修改列名?