获取SQL Server

时间:2016-12-30 16:51:31

标签: c# sql-server sql-server-2012

我想从2016年1月的第一天开始创建startdate,enddate和周数。一周的第一天是星期五。以下是我想要的示例。

设定星期的第一天是星期五

Start Date  EndDate WeekNumber
1/1/2016    7/1/2016    1
8/1/2016    14/1/2016   2
15/1/2016   21/1/2016   3
…..     
……      
…..     
30/12/2016  5/1/2017    53
6/1/2017    12/1/2017   1
13/1/2017   19/1/2017   2
20/1/2017   26/1/2017   3
…       
….      
…       
请给我任何想法。

我可以通过这种方式在星期五的第一天

SET DATEFIRST 5
SELECT  DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE)) [WeekStart],
        DATEADD(DAY, 7 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE)) [WeekEnd]

以这种方式获得周数

SELECT { fn WEEK( '2016-01-01') }

3 个答案:

答案 0 :(得分:1)

它在@StartDate和@StartDate + @NumYears之间产生了整周的系列:

您可以更改开始日期和结束日期,但请注意MAXRECURSION。

<html>
  <head>
   <title>Demo Model</title>
  </head>
  <body>
  <?php
     $_id = $_GET["id"];
     $_time = $_GET["time"];
     $_snr = $_GET["snr"];
     $_station = $_GET["station"];
     $_lat = $_GET["lat"];
     $_lng = $_GET["lng"];
     $_rssi = $_GET["rssi"];
     $_data = $_GET["data"];
     $_avgSnr = $_GET["avgSnr"];

     if ( $fl = fopen('data.json','a')) {
       fwrite($fl,"\"data\": { \"id\" : \"". $_id . "\", "
                             ."\"data\" :\"" . $_data . "\", "
                             ."\"from\" :\"" . $_station . "\", "
                             ."\"lat\" :\"" . $_lat . "\", "
                             ."\"lng\" :\"" . $_lng . "\" }\n" );
       fclose($fl);
     }
  ?>
  </body>
</html>

CREATE FUNCTION fnWeek(@StartDate DATETIME) RETURNS @Weeks TABLE (StartWeekDate DATETIME, EndWeekDate DATETIME, WeekOfYear int) AS BEGIN DECLARE @NumYears int = 2; ;WITH genDates AS ( SELECT @StartDate AS mdate UNION ALL SELECT DATEADD(week, 1, mdate) FROM genDates WHERE DATEADD(week, 1, mdate) < DATEADD(year, @NumYears, @StartDate) ) INSERT INTO @Weeks SELECT mdate AS StartDate, DATEADD(day,6,mdate) AS EndDate, DATEPART(week, mdate) AS WeekOfYear FROM genDates OPTION (MAXRECURSION 0); RETURN; END GO select * from fnWeek('2016-01-01'); 可以添加为参数:

@NumYears

答案 1 :(得分:0)

首先,您需要一个函数来获取两个日期之间的日期,因此应创建以下函数:

CREATE FUNCTION [dbo].[GetDatesBetween](@dateFrom AS DATE, @dateTo AS DATE)
    returns table as
return (
    with 
     N0 as (SELECT 1 as n UNION ALL SELECT 1)
    ,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
    ,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
    ,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
    ,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
    ,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
    ,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
    ,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
    SELECT DATEADD(day,num-1,@dateFrom) as thedate
    FROM nums
    WHERE num <= DATEDIFF(day,@dateFrom,@dateTo) + 1
    );

然后,执行以下查询以获得所需的结果:

DECLARE @dteFROM DATE = '2016-01-01'
DECLARE @dteTo   DATE = '2017-01-26'

;WITH cteDaysInfo AS
(
    SELECT  theDate,
            YEAR(thedate) YearValue,
            DATEDIFF(day, CAST(YEAR(thedate) AS VARCHAR), CAST(YEAR(thedate) + 1 AS VARCHAR)) DaysInYear,
            datediff(week, CAST(YEAR(thedate) AS VARCHAR), CAST(YEAR(thedate) + 1 AS VARCHAR)) NumberOfWeeksInYear,
            ROW_NUMBER() OVER(ORDER BY theDate) DayNumberContinous,
            DATEPART(dayofyear, thedate) DayNumber,
            ceiling((ROW_NUMBER() OVER(ORDER BY theDate)) - 1) / 7 + 1 WeekNumberContinous,
            DATEPART(WEEK, theDate) WeekNumber
    FROM    dbo.GetDatesBetween(@dteFROM, @dteTo)
)

, cteBaseWeeksInfo AS
(
    SELECT  YearValue,
            (SELECT MIN(theDate) FROM cteDaysInfo t2 WHERE t2.YearValue = t1.YearValue and t2.WeekNumberContinous = t1.WeekNumberContinous) StartDate,
            (SELECT MAX(theDate) FROM cteDaysInfo t2 WHERE t2.YearValue = t1.YearValue and t2.WeekNumberContinous = t1.WeekNumberContinous) EndDate,
            t1.WeekNumberContinous,
            (SELECT MIN(WeekNumber) FROM cteDaysInfo t2 WHERE t2.YearValue = t1.YearValue and t2.WeekNumberContinous = t1.WeekNumberContinous) WeekNumber
    FROM    cteDaysInfo t1
    GROUP   BY YearValue, WeekNumberContinous
)

SELECT  (SELECT MIN(StartDate) FROM cteBaseWeeksInfo t2 WHERE t2.WeekNumberContinous = t1.WeekNumberContinous) StartDate,
        (SELECT MAX(EndDate) FROM cteBaseWeeksInfo t2 WHERE t2.WeekNumberContinous = t1.WeekNumberContinous) EndDate,
        (SELECT MAX(WeekNumber) FROM cteBaseWeeksInfo t2 WHERE t2.WeekNumberContinous = t1.WeekNumberContinous) EndDate
FROM    cteBaseWeeksInfo t1
GROUP   BY WeekNumberContinous

答案 2 :(得分:0)

以下解决方案不使用递归:

DECLARE @Year SMALLINT = 2016

DECLARE @FirstDayOfYear DATE = DATEFROMPARTS(@Year, 1, 1)
DECLARE @LastDayOfYear  DATE = DATEFROMPARTS(@Year, 12, 31)
DECLARE @FirstFriday    DATE = DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, '1900-01-01', @FirstDayOfYear), '1900-01-01'))

SET DATEFIRST 5
SELECT y.*, DATEPART(WEEK, y.FirstDayOfWeek) AS WeekNum
FROM (
    SELECT  FirstDayOfWeek  = DATEADD(WEEK, v.number, @FirstFriday), 
            LastDayOfWeek   = DATEADD(DAY, -1, DATEADD(WEEK, 1, DATEADD(WEEK, v.number, @FirstFriday))) 
    FROM    master.dbo.spt_values v -- Instead of this system table, a tally table could be used with all numbers from 0 to 100/1000/10000/etc. (min 54 values: [0..53])
    WHERE   v.type = 'P' -- number = [0..2048]
    AND     v.number <= 53) AS y
WHERE   @FirstDayOfYear <= y.LastDayOfWeek
AND     y.FirstDayOfWeek <= @LastDayOfYear

2016年结果:

FirstDayOfWeek LastDayOfWeek WeekNum
-------------- ------------- -----------
2016-01-01     2016-01-07    1
2016-01-08     2016-01-14    2
2016-01-15     2016-01-21    3
2016-01-22     2016-01-28    4
2016-01-29     2016-02-04    5
...

2017年结果:

FirstDayOfWeek LastDayOfWeek WeekNum
-------------- ------------- -----------
2016-12-30     2017-01-05    53
2017-01-06     2017-01-12    2
2017-01-13     2017-01-19    3
2017-01-20     2017-01-26    4
2017-01-27     2017-02-02    5
...