【问题标题】:SQL Query errors doesn't return values for FridaysSQL 查询错误不返回星期五的值
【发布时间】:2011-06-14 17:44:40
【问题描述】:

我有这个 sql 存储过程,它应该查看特定表并根据日期列返回作业编号。这很好用,除了周六早上运行(并且应该返回所有日期为星期五的工作编号,但不返回任何行)。有什么建议么?这里有一些我没有看到的逻辑问题吗?我怎样才能找到它?

存储过程

ALTER Procedure [dbo].[JC_GetJobsClosedYesterday]

As

SELECT [JobNumber]
  FROM [NCLGS].[dbo].[JobClosedDate]
  Where LastInvoiceDate between dbo.ufn_StartOfDay (DATEADD(d, -1, GETDATE())) AND dbo.ufn_StartOfDay (GETDATE())
  order by JobNumber desc

还有一天的开始功能。

ALTER function [dbo].[ufn_StartOfDay] ( @inDate datetime )

RETURNS DateTime AS 
BEGIN   
DECLARE @Now datetime   
set @Now = @inDate
DECLARE @DayStart datetime
set @DayStart = @Now

set @DayStart = DATEADD (ms, -DATEPART(ms,@Now),@DayStart)
set @DayStart = DATEADD (s, -DATEPART(s,@Now),@DayStart)
set @DayStart = DATEADD (mi, -DATEPART(mi,@Now),@DayStart)
set @DayStart = DATEADD (hh, -DATEPART(hh,@Now),@DayStart)

return @DayStart 
END

编辑:我的日期转换没有问题(除非它不知道如何处理星期五)。我需要返回无行部分的帮助。

样本数据:

JobNumber   LastInvoiceDate             DayOfWeek
112117      2011-06-13 00:00:00.000     Monday
112089      2011-06-10 00:00:00.000     Friday
112090      2011-06-10 00:00:00.000     Friday
112068      2011-06-10 00:00:00.000     Friday
112082      2011-06-10 00:00:00.000     Friday

更新:现在我真的很困惑。这种“周五没有数据”的事情一直在发生(上周五再次发生),但我仍然无法弄清楚。 GETDATE() 是否有可能没有返回我认为返回的内容?因为当我根据@Thomas 的建议尝试以下修改时,两种方法都获取了数据,但是最后基于此代码生成的报告没有数据。

DECLARE @date datetime
--SET @date = '2011-06-21 13:42:27.257'
SET @date = '2011-06-11 03:42:27.257'

--Original Code
SELECT [JobNumber]
  FROM [NCLGS].[dbo].[JobClosedDate]
  Where LastInvoiceDate between dbo.ufn_StartOfDay (DATEADD(d, -1, @date)) AND dbo.ufn_StartOfDay (@date)
  order by JobNumber desc

  --Returns 21 records

--Modified based on @Thomas suggestion
Select [JobNumber]
From [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate >= DateAdd( d, DateDiff( d, 0, @date ) - 1, 0 )
    And LastInvoiceDate < DateAdd( d, DateDiff( d, 0, @date ), 0 )
Order By JobNumber Desc

  --Returns 21 records

【问题讨论】:

  • 为什么不能使用 CONVERT(varchar,getdate(),101)
  • @THEn - 没有理由。这是我继承的代码。
  • 您是否有至少 1 行未显示的示例数据......
  • @MAW74656,抛开性能不谈,我看到的唯一逻辑问题是between 包含两个端点。根据您的样本数据,什么不起作用? (即查询何时运行,返回了什么,应该返回什么?)
  • @MAW74656 - 是不是拉下数据上周五上周五上周六我>?前者意味着该例程在周六运行以获取周五的数据。后两者意味着可能在例程本身而不是查询的运行中出现了问题。

标签: sql tsql sql-server-2000


【解决方案1】:

您应该使用返回前一天开始的表达式,而不是DATEADD(d, -1, GETDATE())。您可以为此使用 dbo.ufn_StartOfDay() 函数,但还有更简单的方法:

Select @DayStart = DateAdd( d, DateDiff( d, 0, @inDate ), 0 )

这意味着:将 nil 时间戳增加 nil 时间戳和给定时间戳之间的整数天数

我还建议使用该表达式而不是已经存在的函数调用,因此您的查询将是:

Select [JobNumber]
From [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate Between DateAdd( d, DateDiff( d, 0, GetDate() ) - 1, 0 )
                          And DateAdd( d, DateDiff( d, 0, GetDate() ),     0 )
Order By JobNumber Desc

加法

您需要更清楚问题到底出在哪里。这是我创建的示例查询,它测试从 6 月 9 日星期四到 6 月 18 日星期六的每个日期。您希望在哪个日期获得值但没有得到值,反之亦然:

With SampleData As
    (
    Select 112117 As JobNumber, '2011-06-13 00:00:00.000' As LastInvoiceDate, 'Monday' As DayOfWeek
    Union All Select 112089, '2011-06-10 00:00:00.000', 'Friday'
    Union All Select 112090, '2011-06-10 00:00:00.000', 'Friday'
    Union All Select 112068, '2011-06-10 00:00:00.000', 'Friday'
    Union All Select 112082, '2011-06-10 00:00:00.000', 'Friday'
    )
    , TestDates As
    (
    Select Cast('20110609' As datetime) As Date
    Union All
    Select DateAdd(d,1,Date)
    From TestDates
    Where Date <= '20110617'
    )
Select TD.Date, DateName(dw,TD.Date), Count(SD.JobNumber)
From TestDates As TD
    Left Join SampleData As SD
        On SD.LastInvoiceDate Between DateAdd( d, DateDiff( d, 0, TD.Date ) - 1, 0 )
                          And DateAdd( d, DateDiff( d, 0, TD.Date ),     0 )

Group By TD.Date

更新

在查看您的 cmets 和代码时,我认为问题在于您对 Between 的使用。 Col Between DateA And DateB 转换为 Col &gt;= DateA And Col &lt;= DateB。即,它包括两个端点。相反,您需要排除最终终点:

Select [JobNumber]
From [NCLGS].[dbo].[JobClosedDate]
Where LastInvoiceDate >= DateAdd( d, DateDiff( d, 0, GetDate() ) - 1, 0 )
    And LastInvoiceDate < DateAdd( d, DateDiff( d, 0, GetDate() ), 0 )
Order By JobNumber Desc

这将为您提供前一天的所有工作编号。即,如果今天是 2011 年 6 月 10 日星期五,它将为您提供从 2011-06-09 midnight2011-06-09 23:59:59 的所有 LastInvoiceDate 值。

【讨论】:

  • @Thomas @Andriy - 我明白你的意思,但是当我通过函数 GETDATE() 时,它会返回正确的日期时间:2011-06-14 00:00:00.000
  • @MAW74656 - 没关系。您希望 SQL 今天的日期作为实际的 DateTime,以便您可以对其进行数学运算。如果您尝试将今天的日期作为值返回,请按原样返回并将其格式化在您的报告或输出(例如 Excel)中。
  • @Thomas - 对不起,我不明白。您是说根据数学要求我的代码看起来还可以吗?
  • @MAW74656 - 我是说有一种更快的方法来获得你所寻求的,即从日期时间中剥离时间部分并获取昨天和今天的日期。即,您不需要 UDF。
  • @MAW74656 - 顺便说一句,您的函数在剥离时间部分方面确实返回了正确的结果。如果您有一个未返回正确数据的特定数据值,则应提供该值。我的猜测是确定“星期六早上”。
【解决方案2】:

Floor a date in SQL server

要剥离时间部分,请使用:

 SELECT CAST(FLOOR(CAST(CURRENT_TIMESTAMP AS float)) AS DATETIME)

这应该是最快的方法。因此

SELECT [JobNumber]
  FROM [NCLGS].[dbo].[JobClosedDate]
  WHERE LastInvoiceDate between 
       CAST((FLOOR(CAST(GETDATE() float))-1.0) AS DATETIME) AND
        CAST(FLOOR(CAST(GETDATE() AS float)) AS DATETIME)
  ORDER BY JobNumber DESC

【讨论】:

  • 问题不在于剥离时间部分。这是一个没有问题的解决方案。
  • @MAW7465 - 你让我明白了......你的问题是没有问题的 - 测试数据到底是什么,你没想到的结果是什么?
【解决方案3】:

更新作业关闭表的过程在周一、周二、周三、周四和周五早上运行。它在星期六不运行,因此直到星期一才插入记录,届时我的存储过程将不会检索它们。我也会安排更新作业在星期六运行。

我在 select 语句之前添加了以下内容:

if datepart(dw, GETDATE()) = 7 OR datepart(dw, GETDATE()) = 1
    BEGIN
        Exec dbo.NCL_MaintainJobClosedDateTable
        --Select 'True'
    END

这将强制在周六和周日早上进行更新。

【讨论】:

    猜你喜欢
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 2018-11-26
    相关资源
    最近更新 更多