【问题标题】:Avoiding computed columns code duplication in SQL Server SELECT statement避免 SQL Server SELECT 语句中的计算列代码重复
【发布时间】:2021-10-14 21:41:03
【问题描述】:

我正在尝试构建一个 SELECT 查询,一旦完成,我最终会变成一个视图,我从表中选择一堆列,然后有一系列 CASE 语句来填充计算列。但是,我是 SQL 新手,因此不确定最好的方法。

我目前正在计算插入每个案例语句的日期差异,并且发现自己在每个 CASE 语句中重复相同的日期差异计算并且来自 OOP 背景,这不是 DRY 并且感觉可以改进。请参阅下面的代码 sn-p。

SELECT TOP 1000
   Col1
   Col2
   CASE
      WHEN t.Col1 = 'X' and DATEDIFF(month, try_convert(datetime, try_convert(varchar(8), 
      YYYYMMDD)), getdate())/12 <= 5 then 'Not Included'
      WHEN t.Col1 = 'X' and DATEDIFF(month, try_convert(datetime, try_convert(varchar(8), 
      YYYYMMDD)), getdate())/12 > 5 then 'Included'
      WHEN t.Col1 = 'X' and DATEDIFF(month, try_convert(datetime, try_convert(varchar(8), 
      YYYYMMDD)), getdate())/12 IS NULL then 'Included'
   END AS List
from db.Table t

以上是我到目前为止所采用的一般结构,但最终产品将有 6 个更多的案例陈述,所有这些陈述都包括相同的 DATEDIFF 计算。任何人都可以提供一些技巧来使这更加干燥并减少代码复制吗?

编辑:YYYYMMDD 部分是指我试图转换为日期的整数值,以计算年份差异。

非常感谢!

【问题讨论】:

  • 使用 CTE 或子查询来计算值。尽管该表达式很奇怪——为什么将日期转换为字符串然后再转换回日期?如果YYYYMMDDdate 字段,那么您需要做的就是datediff(month,yyyymmdd,getdate())。如果不是,那是什么?为什么它不是 date
  • 嗨 Panagiotis,对不起,我应该澄清一下,我要转换的东西是 YYYYMMDD 格式的整数值,据我所知,这是将其转换为的一种方法需要的格式?
  • 为什么这不是date?这是正确的便携式类型,它允许您使用所有与日期相关的功能。它占用的空间也更少。所有转换都会导致问题,因为它们会阻止索引的使用。使用错误的类型也允许存储无效值,这可能是您使用 TRY_CONVERT 而不是 cast 的原因
  • 为什么整数 YYYYMMDD 不是日期?不幸的是,这只是我收到的 YYYYMMDD 数据的格式。我将尝试向后工作,看看是否可以让数据提供者以日期格式提供它并使用您的方法,因为它看起来更强大!谢谢
  • date 是特定的 SQL Server 数据类型,而不是格式。 YYYYMMDDYYYY-MM-DD 形式的字符串可以轻松转换为 date

标签: sql sql-server


【解决方案1】:

我使用 CROSS APPLY 表示 DRY。我宁愿从当前日期减去 5 年,然后进行比较:

SELECT
    Col1,
    Col2,
    CASE WHEN Col1 = 'X' THEN
        CASE WHEN YYYYMMDD > refdate THEN 'Not Included' ELSE 'Included' END
    END
FROM t
CROSS APPLY (SELECT DATEADD(YEAR, -5, CURRENT_TIMESTAMP) AS refdate) AS ca

【讨论】:

    【解决方案2】:

    您需要添加 1 个选择语句层。

    检查以下方式。

     select Col1,Col2,
    CASE
          WHEN m.Col1 = 'X' and m.Value <= 5 then 'Not Included'
          WHEN m.Col1 = 'X' and m.Value > 5 then 'Included'
          WHEN m.Col1 = 'X' and m.Value IS NULL then 'Included'
       END AS List
     from 
    (
    select Col1,Col2, DATEDIFF(month, try_convert(datetime, try_convert(varchar(8), 
          YYYYMMDD)), getdate())/12 as Value
    from db.Table t
    ) m
    

    【讨论】:

    • 嗨@Malvik Bhavsar,效果很好,感谢您的帮助!将来我肯定会使用这些额外的选择语句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 2020-03-16
    • 1970-01-01
    • 2020-02-14
    • 2016-12-18
    • 2019-02-19
    相关资源
    最近更新 更多