我在使用日期时间字段的查询时遇到问题。
因为我将datetime字段转换为-varchar(10),..,103-所以我可以在103格式而不是datetime上应用带有日期字段的where子句但是当我使用where子句时它不显示结果或者按我需要的方式分组,因为datetime字段已转换为字符串。
以下是该示例的简化查询:
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组合对象。
答案 0 :(得分:3)
请勿使用CONVERT(VARCHAR, DateField, 103)
从DATETIME
中删除效率低的时间,并在排序时造成问题。
根据您使用的SQL-Server版本,有两个选项通常被视为最佳选项。对于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子句中字符串的部分仍然相关。此外,只有很少的时候才需要以字符串格式向您的应用程序提供日期。最好将日期保留为日期并将其格式化在您的应用程序层中(无论这可能是什么)。
答案 1 :(得分:0)
不要在GROUP BY中使用CONVERT,也不要在WHERE中使用。在SELECT字段列表中使用转换
<强>更新强>
请参阅Microsoft的DATE CONSTANTS的有效和推荐格式。请选择“DATEFORMAT dependent:NO”和“Multilanguage:YES”的任何格式,以便在任何语言/设置中没有任何问题
<强>更新强>
当我看到时,我正在编写同样的查询@Blorgbeard:它不会工作,因为你不能只通过nbranch进行分组并且在选择列表上有ddate,而且在group by上的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
答案 2 :(得分: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
。
答案 3 :(得分:0)
您可以将文件日期转换为:
ISNULL(CONVERT(varchar(12),tranInwardHeader.DocumentDate,103),'') AS DocumentDate