如何按周获取数据库值

时间:2013-09-26 11:23:28

标签: sql sql-server-2008

我只想问一下如何在一个月内按周获取数据库中的记录?使用sql 我的意思是,当我输入1时,它将在一个月的第一周获得记录 我今天做了很多研究,但似乎无法找到一个好的解决方案

下面是代码:

DECLARE @MONTH int
DECLARE @YEAR int
DECLARE @WEEK int

SET @MONTH = 9
SET @YEAR = 2013
SET @WEEK = 1

SELECT RH.RepairOrderNumber FROM dbo.RepairOrderHeader RH
WHERE MONTH(RH.DateReleased) = @MONTH AND YEAR(RH.DateReleased) = @YEAR AND WEEK(RH.DateReleased) = @WEEK

我只想根据月份,年份和星期取出记录,有没有任何方法和准确的代码如何做到这一点?

4 个答案:

答案 0 :(得分:0)

DATEPART(WEEK,)为您提供一年中的一周数量,因此您只需计算当月日周数与当月第一天的周数之间的差异:

WHERE MONTH(RH.DateReleased) = @MONTH 
  AND YEAR(RH.DateReleased) = @YEAR 
  AND DATEPART(WEEK,RH.DateReleased)
       -DATEPART(WEEK,DATEADD(DAY,-DAY(RH.DateReleased)+1,RH.DateReleased))+1 
       = @WEEK

答案 1 :(得分:0)

WEEK返回一年中的一周,从一周中的一天(即每个星期日)开始。你好像想要这个月的那个星期,我猜这个星期总是在每个月的1号开始。

这样:

SELECT RH.RepairOrderNumber FROM dbo.RepairOrderHeader RH
WHERE  MONTH(RH.DateReleased) = @MONTH AND 
       YEAR(RH.DateReleased) = @YEAR AND 
       DAY(RH.DateReleased) / 7 + 1 = @WEEK

答案 2 :(得分:0)

尽可能避免在WHERE子句中使用列上的函数。您立即失去了利用这些列上的索引的能力。以下解决方案提供与选择答案相同的结果,但表现更好:

DECLARE @MONTH INT = 9
DECLARE @YEAR INT = 2013
DECLARE @WEEK INT = 2

--1ST OF THE MONTH DECLARED
DECLARE @Date DATE = CAST(CAST(@Year AS VARCHAR(4)) + 
                    RIGHT('0' + CAST(@Month AS VARCHAR(2)), 2) + '01' AS DATE)

SET  @Date = DATEADD(WEEK, @Week - 1, DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date));

SELECT  RH.RepairOrderNumber 
FROM    dbo.RepairOrderHeader RH
WHERE   RH.DateReleased >= @Date
AND     RH.DateReleased < DATEADD(WEEK, 1, @Date);

所有这一切都是获得当月的第一天,然后找到该月的第一天所在的第一天。然后将声明的周数添加到此日期。

使用包含6年数据和每天10行(20,480条记录,因此不是很多)的示例表以及日期列上的索引,此处的执行计划和接受的答案如下(接受于顶部,使用底部的日期):

enter image description here

Testing DDL and queries on SQL-Fiddle

这表明当您使用WEEK(DateColumn) = @Week时根本不使用索引,并且查询成本要高得多。根据表中数据的分布情况,这可能会产生巨大的差异,即使在我的示例中的小数据集中,它的效率也提高了800%。

答案 3 :(得分:0)

我认为'2013-08-26' - '2013-09-01'是九月的第一周

DECLARE @MONTH int = 9
DECLARE @YEAR int = 2013
DECLARE @WEEK int = 1

DECLARE @from date= dateadd(day, datediff(day, -(@WEEK - 1)*7, 
       (dateadd(month, (@year-1900) * 12 + @month - 1 , 0)))/7*7 , 0)

SELECT RH.RepairOrderNumber 
FROM dbo.RepairOrderHeader RH
WHERE RH.DateReleased >= @from
and RH.DateReleased < dateadd(week, 1, @from)