【问题标题】:SQL - date variable isn't being parsed correctly?SQL - 日期变量没有被正确解析?
【发布时间】:2013-10-30 04:02:59
【问题描述】:

我正在提取按开始和结束日期过滤的发票列表,并从 SQL 表中按发票类型进一步过滤。当我指定 2013-07-01 到 2013-09-30 的范围时,我预计每家公司收到 2 张发票,而我预计 3 张。当我在 SSMS 中使用内置的 select top 1000 查询并添加我的日期过滤器时,所有预期出现发票。

这是我使用输入变量的奇特查询:

DECLARE @ReportStart datetime
DECLARE @ReportStop datetime

SET @ReportStart = '2013-07-01'
SET @ReportStop = '2013-09-30'

SELECT Entity_Company.CompanyName,
Reporting_AgreementTypes.Description,
Reporting_Invoices.InvoiceAmount,
ISNULL(Reporting_ProductCost.ProductCost,0),
(Reporting_Invoices.InvoiceAmount - ISNULL(Reporting_ProductCost.ProductCost,0)),
(Reporting_AgreementTypes.Description + Entity_Company.CompanyName),
Reporting_Invoices.InvoiceDate
FROM Reporting_Invoices
JOIN Entity_Company ON Entity_Company.ClientID = Reporting_Invoices.ClientID
LEFT JOIN Reporting_ProductCost ON Reporting_ProductCost.InvoiceNumber =Reporting_Invoices.InvoiceNumber
JOIN Reporting_AgreementTypes ON Reporting_AgreementTypes.AgreementTypeID = Reporting_Invoices.AgreementTypeID
WHERE Reporting_Invoices.AgreementTypeID = (SELECT AgreementTypeID FROM Reporting_AgreementTypes WHERE Description = 'Resold Services')
AND Reporting_Invoices.InvoiceDate >= @ReportStart AND Reporting_Invoices.InvoiceDate <= @ReportStop

ORDER BY CompanyName,InvoiceDate

以上仅返回每家公司 2 张发票。当我通过 SSMS 运行更基本的查询时,我得到了 3 的预期结果,如下所示:

SELECT TOP 1000 [InvoiceID]
      ,[AgreementID]
      ,[AgreementTypeID]
      ,[InvoiceDate]
      ,[Comment]
      ,[InvoiceAmount]
      ,[InvoiceNumber]
      ,[TicketID]
      ,Entity_Company.CompanyName
  FROM Reporting_Invoices
  JOIN Entity_Company ON Entity_Company.ClientID = Reporting_Invoices.ClientID
  WHERE Entity_Company.ClientID = '9' AND 
  AgreementTypeID = (SELECT AgreementTypeID FROM Reporting_AgreementTypes WHERE Description = 'Resold Services')

  AND Reporting_Invoices.InvoiceDate >= '2013-07-01' AND Reporting_Invoices.InvoiceDate <= '2013-09-30'

  ORDER BY InvoiceDate DESC

我已尝试剥离第一个查询,只包含原始发票表中的客户 ID、发票日期,不包括其他内容。仍然只得到 2 张发票,而不是预期的 3 张。我也尝试手动输入日期而不是 @ 变量,结果相同。我确认 InvoiceDate 被定义为表中的日期时间。我已经尝试将所有 JOIN 都设为 FULL JOIN,以查看是否隐藏了任何东西,但没有任何变化。以下是我如何剥离原始查询以将所有其他表排除在外,但每个客户 ID 仍然只收到 2 张发票,而不是 3 张(我手动输入了类型过滤器的 ID):

--DECLARE @ReportStart datetime
--DECLARE @ReportStop datetime

--SET @ReportStart = '2013-07-01'
--SET @ReportStop = '2013-09-30'

SELECT --Entity_Company.CompanyName,
--Reporting_AgreementTypes.Description,
Reporting_Invoices.ClientID,
Reporting_Invoices.InvoiceAmount,
--ISNULL(Reporting_ProductCost.ProductCost,0),
--(Reporting_Invoices.InvoiceAmount - ISNULL(Reporting_ProductCost.ProductCost,0)),
--(Reporting_AgreementTypes.Description + Entity_Company.CompanyName),
Reporting_Invoices.InvoiceDate
FROM Reporting_Invoices
--JOIN Entity_Company ON Entity_Company.ClientID = Reporting_Invoices.ClientID
--LEFT JOIN Reporting_ProductCost ON Reporting_ProductCost.InvoiceNumber = Reporting_Invoices.InvoiceNumber
--JOIN Reporting_AgreementTypes ON Reporting_AgreementTypes.AgreementTypeID = Reporting_Invoices.AgreementTypeID
WHERE Reporting_Invoices.AgreementTypeID = '22'-- (SELECT AgreementTypeID FROM Reporting_AgreementTypes WHERE Description = 'Resold Services')
AND Reporting_Invoices.InvoiceDate >= '2013-07-01' AND Reporting_Invoices.InvoiceDate <= '2013-09-30'

ORDER BY ClientID,InvoiceDate

这让我觉得很奇怪,因为它与 SSMS 生成的返回正确结果的查询几乎相同。我忽略了什么?

更新

我进一步完善了我的“测试查询”,每家公司仅返回 2 张发票,以帮助解决此问题。以下是相应表格中 1 家公司的查询和相关数据子集:

SELECT Reporting_Invoices.ClientID,
Reporting_AgreementTypes.Description,
Reporting_Invoices.InvoiceAmount,
Reporting_Invoices.InvoiceDate
FROM Reporting_Invoices
JOIN Reporting_AgreementTypes ON Reporting_AgreementTypes.AgreementTypeID = Reporting_Invoices.AgreementTypeID
WHERE Reporting_Invoices.AgreementTypeID = (SELECT AgreementTypeID FROM Reporting_AgreementTypes WHERE Description = 'Resold Services')
AND Reporting_Invoices.InvoiceDate >= '2013-07-01T00:00:00' AND Reporting_Invoices.InvoiceDate <= '2013-09-30T00:00:00'

ORDER BY Reporting_Invoices.ClientID,InvoiceDate

以上仅返回 2 张发票。以下是相关表格数据:

Relevant data from Reporting_AgreementTypes         
AgreementTypeID Description     
22              Resold Services     

Relevant data from Reporting_Invoices           
InvoiceID   ClientID    AgreementID AgreementTypeID     InvoiceDate
16111     9         757         22                  2013-09-30 00:00:00.000
15790     9         757         22                  2013-08-30 00:00:00.000
15517     9         757         22                  2013-07-31 00:00:00.000

Actual results from my new modified query           
ClientID    Description InvoiceAmount   InvoiceDate
9           Resold Services 3513.79         7/31/13 00:00:00
9        Resold Services    3570.49         8/30/13 00:00:00

【问题讨论】:

  • 日期格式有什么奇怪的地方吗?我有类似的东西,不知何故它应用了一些本地化并给出了意想不到的结果..
  • 万一yyyy-mm-dd 被解释为yyyy-dd-mm(这可能发生在SET LANGUAGE FRENCH; 等场景中),您是否尝试使用真正明确的格式(yyyymmdd)来代替?您需要显示一些示例数据和包含但不应该包含的行(或相反)。
  • 这就是我的想法,因为它没有将时间设置为 00:00:00,因此放弃了 9/30 的发票。我尝试将 @ vars 设置为日期的 ISO 标准并得到相同的结果。还尝试了 20130701 和 20130930 。这是我使用的时间:SET ReportStart = '2013-07-01T00:00:00' SET ReportStop = '2013-09-30T00:00:00' (不能在评论中使用@)
  • 试试Reporting_Invoices.InvoiceDate &lt; '2013-10-01'
  • 我将获取带有已清理公司名称的样本数据并立即更新问题。

标签: sql sql-server filter


【解决方案1】:

检查 1:您确定查看的是同一个数据库吗?检查 SSMS 中的右下角。


检查 2: 在不同的 dateformatlanguage 选项下,日期意味着不同的东西。例如,日期2013-01-02 表示法国的 2 月 1 日:

set language french
select cast('2010-02-01' as datetime)
--> 2010-01-02 00:00:00.000
set language us_english
select cast('2010-02-01' as datetime)
--> 2010-02-01 00:00:00.000
set dateformat ydm
select cast('2010-02-01' as datetime)
--> 2010-01-02 00:00:00.000

您可以通过以下方式显示当前日期格式选项:

select  s.date_format
,       s.language 
from    sys.dm_exec_sessions s
where   s.session_id = @@spid

将上述查询放在其他两个查询之上并比较结果。


检查 3:打开事务的效果仅在其自己的会话中可见。因此,请检查是否有任何未结交易。你可以这样做:

dbcc opentran

检查 4: 该列的类型是否与您要比较的类型不同?如果是这样,SQL Server 会将lower precedence 的数据类型转换为优先级更高的数据类型。

这是一个例子:

create table t1 (dt date);
insert t1 values ('2010-01-01');
select * from t1 where dt = '1 Jan 2010'

这将返回一行,因为date 的优先级高于varchar。所以'1 Jan 2010' 被转换为date。如果反过来,'2010-01-01' 将无法匹配匹配 '1 Jan 2010'

【讨论】:

  • 我的结果是:mdy us_english
  • 两个查询都是这样吗?
  • 是的,忘记在我最后的评论中添加。
  • 是否有未结交易?检查添加的查询。
  • 刚刚运行了两个版本来检查未结交易,但没有。
【解决方案2】:

检查事项:

  • 遗失的发票是 '2013-09-30' 吗?
  • InvoiceDate 实际上是带有时间元素的日期时间吗?

如果您要比较日期时间,则除非指定,否则时间为 00:00,这将排除该日期的大部分时间。如果你想包含它,那么你可以使用

 < '2013-10-01'

 convert(date, InvoiceDate) <= '2013-09-30'

【讨论】:

  • 这就是我最初的想法,所以我使用了 '2013-09-30T00:00:00' 并得到了相同的结果。我还将结束日期设置为“2013 年 10 月 30 日”以获得下个月,但我仍然只得到 2 个结果。真的很奇怪。
  • 这些是 cmets,不是答案。
  • @Colin'tHart 否。它们是识别问题的步骤。
  • 即 cmets,不是答案。
  • @BillSambrone invoicingdate 字段实际上是日期还是字符串?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多