【发布时间】:2016-03-09 04:48:07
【问题描述】:
我有一个 SQL 查询如下:
SELECT [ClientId]
,[LastDelivery]
,[LastRequisitionDate]
,Datediff (day, LastRequisitionDate, LastDelivery) as DiffDate
FROM [dbo].[App_Client]
where (LastDelivery != '1900-01-01 00:00:00'
and LastRequisitionDate != '1900-01-01 00:00:00')
and Inactive = 0
and (Datediff (day, LastRequisitionDate, LastDelivery) < 9)
and (Datediff (day, LastRequisitionDate, LastDelivery) >= 0)
我有一份客户名单,我希望所有客户在申请后 8 天内收到货。原因
LastDelivery != '1900-01-01 00:00:00'
and LastRequisitionDate != '1900-01-01 00:00:00'
是因为我的 c# 查询方式要求任何日期字段中都没有空字段(这些字段在数据库中可以为空,但它们确实不应该)。我有一个包含 11838 个客户端的数据库,此查询返回 10404。我的问题是我无法使用 C# linq 复制此查询。
我的 C# 查询如下:
var clients = _clientService.GetAllClients().Where(x =>
(x.LastDelivery != Convert.ToDateTime("01/01/1900")
&& x.LastRequisitionDate != Convert.ToDateTime("01/01/1900"))
&& x.Inactive == 0
&& (((DateTime)x.LastDelivery - (DateTime)x.LastRequisitionDate).Days < 9)
&& (((DateTime)x.LastDelivery - (DateTime)x.LastRequisitionDate).Days >= 0)).ToList();
这个查询返回 10563 个结果,相差 159,我根本不知道哪里出错了。对我来说,C# 查询看起来与 SQL 查询相同,但在某处存在差异。我整天都在编码,所以也许我有点筋疲力尽,解决方案很明显,但我就是看不到。谁能提供帮助或建议我可能做错了什么或忽略了什么?
回答
正如马特史密斯在下面正确指出的那样,事实证明这两个查询都是正确的 - 差异在于 SQL DateDiff 函数,它测量 1 天,当一天经过午夜时,这意味着比较 2016 年 1 月 1 日 23:59 :59 和 01/02/2016 00:00:01 给出了一天的差异,而在我的 C# 查询中,它将天数的实际差异作为时间跨度(24 小时)进行比较。多亏了马特·史密斯,伟大的发现和重要的区别。
【问题讨论】:
-
那么,将生成的 SQL 与您的原始 SQL 进行比较。
-
我不知道该怎么做...
-
您正在使用 EntityFramework 或其他类似的基于 IQueryable 的系统吗?如果您可能希望将此过滤器移动到“调用堆栈的较低位置”,您似乎正在使用
IEnumerable,因为您执行的操作在 EF 中是不允许的,因此您的数据库正在使用没有过滤器,返回所有行,然后你在内存中过滤,这会给你带来糟糕的性能。 -
您的日期值中有时间组件吗?如果是这样,则 DateDiff 在 SQL 中的工作方式之间存在重要差异,其中 DateDiff(day, '03/06/2016 23:59:59', '03/07/2016 00:00:01') = 1 和.NET 其中 ('03/07/2016 23:00:00' - '03/06/2016 23:59:00').Days = 0。DateDiff(day,x,y) 测量跨越的 Day 边界数. TimeSpan.Days 返回差异的天数部分。
-
好的,我已经把它作为答案发布了。 @ailinmcc666,要检查一下吗?