1

我在使用日期时间字段进行查询时遇到问题。

这是因为我将 datetime 字段转换为 -varchar(10),..,103- 所以我可以在 103 格式上应用带有日期字段的 where 子句而不是 datetime 但是当我使用 where 子句时它不显示结果或分组我需要的方式,因为日期时间字段已转换为字符串。

以下是该示例的简化查询:

select ddate,SUM(ntotal) as Income from Inc_orders    
where nbranch=2 
and convert(varchar(10),ddate,103)                                   
between '01/06/2010' and '31/06/2010'   
group by convert(varchar(10),ddate,103)  
order by ddfecha desc

ddate 是日期时间字段
ntotal 是整数
nbranch 是外键

然后发生的是我从另一个 103 日期范围获得结果

01/10/2009  4447.0000    
02/01/2010  26267.8000    
02/02/2010  20498.0000    
02/04/2010  22565.1000   
02/05/2010  20539.0000    
02/11/2010  33934.3000     
02/12/2009  33587.4000   

我假装的样子是:

01/06/2010  29327.7000       
02/06/2010  31170.4000     
03/06/2010  37737.7000     
04/06/2010  25109.6000     
06/06/2010  20819.7000     
10/06/2010  44703.9000     
14/06/2010  21755.1000     
15/06/2010  39369.3000    
05/06/2010  29552.2000    
07/06/2010  35305.9000    
08/06/2010  30628.6000    
..........     
31/06/2010  18677.6000 

解决方案不使用 datepart、month 或 year 函数,因为我需要该参数看起来像日历才能在其上应用 datetimepicker calentad 组合对象。

4

4 回答 4

3

不要使用CONVERT(VARCHAR, DateField, 103)从中删除时间DATETIME效率低下并且在排序时也会导致问题。

根据您使用的 SQL-Server 版本,有 2 个选项通常被认为是最好的。对于 SQL-Server 2008 及更高版本,请使用CAST(DateField AS DATE),对于以前的版本,请使用DATEADD(DAY, 0, DATEDIFF(DAY, 0, DateField))

因为您在这一行中将 Ddate 转换为 VARCHAR:

convert(varchar(10),ddate,103) between '01/06/2010' and '31/06/2010' 

您正在删除 '01/06/2010' 和 '31/06/2010' 到日期的隐式转换。这意味着 '02/01/2000' 大于 '01/01/2012' 因为您比较的是字符串而不是日期。如果您从 Ddate 中删除时间并将表达式保持为日期(时间)格式,则“01/06/2010”和“31/06/2010”将隐式转换为日期。

为了简单地说明这一点,您可以运行这个简单的查询:

SELECT  CASE WHEN '02/06/2000' BETWEEN '01/06/2012' AND '03/06/2012' THEN 1 ELSE 0 END [String Comparison],
        CASE WHEN CONVERT(DATETIME, '02/06/2000') BETWEEN '01/06/2012' AND '03/06/2012' THEN 1 ELSE 0 END [Date Comparison]

所以你的查询最终会是这样的:

SET DATEFORMAT DMY

SELECT  CAST(DDate AS DATE) Ddate,
        SUM(ntotal) as Income 
FROM    Inc_orders    
WHERE   nbranch=2 
AND     CAST(DDate AS DATE) BETWEEN '01/06/2010' AND '31/06/2010'   
GROUP BY CAST(DDate AS DATE)
ORDER BY DDate

或者

SELECT  DATEADD(DAY, 0, DATEDIFF(DAY, 0, DDate)) Ddate,
        SUM(ntotal) as Income 
FROM    Inc_orders    
WHERE   nbranch=2 
AND     DATEADD(DAY, 0, DATEDIFF(DAY, 0, DDate)) BETWEEN '01/06/2010' AND '31/06/2010'   
GROUP BY DATEADD(DAY, 0, DATEDIFF(DAY, 0, DDate))
ORDER BY DDate

附录

我不确定是否Ddate包含时间,因此使用上述内容删除时间可能不相关,但 where 子句中比较字符串的部分仍然相关。此外,很少有需要以字符串格式向应用程序显示日期的情况。最好将日期保留为日期并在您的应用程序层中对其进行格式化(无论这可能是什么)。

于 2012-06-21T22:14:06.413 回答
0

不要在 GROUP BY 和 WHERE 中使用 CONVERT。在 SELECT 字段列表上使用转换

更新:请参阅Microsoft的DATE CONSTANTS
的 有效和推荐格式。请选择带有“DATEFORMATdependent: NO”和“Multilanguage: YES”的任何格式,以免在任何语言/设置中出现任何问题

更新:
当我看到时,我正在编写相同的查询@Blorgbeard:它不起作用,因为您不能仅按 nbranch 分组并且在选择列表中有 ddate,分组时的 nbranch 也没有意义,因为只有有效值是 2。你需要重新定义您的查询/需求

我想,您的查询可能是:

select ddate,SUM(ntotal) as Income from Inc_orders    
where nbranch=2 
and ddate  between '20100601' and '20100631'   
group by ddate   
order by ddate
于 2012-06-21T21:31:22.030 回答
0

不要将日期转换为字符串,只需将其保留为日期:

select ddate,SUM(ntotal) as Income from Inc_orders    
where nbranch=2 
and ddate between '2010-06-01' and '2010-06-31'
group by nbranch   
order by ddate

ddate如果您希望它以特定方式显示,您可以在选择列表中进行转换。

于 2012-06-21T21:32:51.760 回答
0

您可以通过以下方式转换文档日期:

ISNULL(CONVERT(varchar(12),tranInwardHeader.DocumentDate,103),'') AS DocumentDate
于 2012-06-22T03:07:12.657 回答