【问题标题】:how to date format 103 to group by using where clause with string format (varchar(103),...,10)如何使用字符串格式的 where 子句将日期格式 103 分组(varchar(103),...,10)
【发布时间】:2012-06-24 05:04:21
【问题描述】:

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

这是因为我将 datetime 字段转换为 -varchar(10),..,103- 所以我可以在 103 格式而不是 datetime 上应用带有 date 字段的 where 子句,但是当我使用 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 组合对象。

【问题讨论】:

  • 你为什么要转换日期时间?
  • 我正在对其进行转换,以便我可以应用对象 datetimepicker 在 adoquery for delphi 上放置不同的间隔。也用于以这种方式在网格上显示信息。
  • 只需反过来,将来自 datepicker 的值转换为格式“YYYYMMAA”,您将确保您的应用始终适用于任何输入
  • 好的,但我还需要以 dd/mm/yyyy 格式在网格上显示日期。我要把它应用到其他表格上。 TY
  • 传递给查询的内容和从中获得的内容不同。因此,正如我所建议的,仅在选择列表上使用 CONVERT 以获得最适合您的格式。但是使用标准将参数传递给查询:YYYYMMDD 是一种无失败格式。或者,如果您输入了数据,则使用参数化查询。

标签: sql sql-server datetime varchar


【解决方案1】:

不要使用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 子句中比较字符串的部分仍然相关。此外,很少有需要以字符串格式向应用程序显示日期的情况。最好将日期保留为日期并在您的应用程序层中对其进行格式化(无论这可能是什么)。

【讨论】:

  • 你的回答很完整,我会继续修改这个问题,因为现在它不能那样工作
  • 请不要像CAST(DDate AS DATE) BETWEEN '01/06/2010' AND '31/06/2010'那样使用'DD/MM/YYYY'格式,因为它依赖于语言,而是使用'YYYYMMDD'
  • 全部为您的答案 Luis siquot 我转换了来自日期时间选择器的值,就是这样
  • @LuisSiquot 虽然我同意 YYYYMMDD 是更好的格式,但请注意答案中的查询包含 SET DATEFORMAT DMY 因此使用 DD/MM/YYYY 不依赖于数据库语言设置,因此您的评论没有实际意义。
【解决方案2】:

不要将日期转换为字符串,直接将其保留为日期即可:

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

【讨论】:

  • 感谢您的快速回答。好的,问题是我需要在 where 子句中使用格式 dd/mm/yyyy,
  • 小心'yyyy-mm-dd' - 如果是SET LANGUAGE FRENCH,这会得到不同的解释。使用'yyyymmdd' 更安全。
  • 如何在不改变语言类型的情况下使其与 dd-mm-yyyy 一起工作 :)
【解决方案3】:

您可以将文档日期转换为:

ISNULL(CONVERT(varchar(12),tranInwardHeader.DocumentDate,103),'') AS DocumentDate

【讨论】:

    【解决方案4】:

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

    更新:
    请参阅 Microsoft 的 DATE CONSTANTS 的有效和推荐格式。请选择“依赖于日期格式:否”和“多语言:是”的任何格式,以免在任何语言/设置中出现任何问题

    更新:
    当我看到时,我正在编写相同的查询@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
    

    【讨论】:

    • 我只是将其作为一个运行示例。不要担心错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 2022-07-04
    • 1970-01-01
    相关资源
    最近更新 更多