【问题标题】:Convert number of hours to days and hours in SQL Server (NOT T-SQL)在 SQL Server(不是 T-SQL)中将小时数转换为天数和小时数
【发布时间】:2017-12-12 19:28:21
【问题描述】:

我有几个小时需要以天和小时的格式显示。

这个数字来自DATEDIFF 指令。

对于小于 24 的数字,我希望只显示小时 - 即 21 hours

对于更大的数字,我希望显示日期和小时 - 即,3 days, 14 hours

我不需要显示任何小于小时的单位,并且值应该向下舍入到前一个小时,因此 1 小时 59 分钟将是 1 小时。

我不能使用存储过程 - 这必须作为单个 select 语句运行。

我知道我可以使用模数来计算值,所以假设 71 小时:

select concat((71 - (71 % 24)) / 24, ' days, ', 71 % 24, ' hours')

然而这有点混乱,因为语句必须是单选,我将不得不计算DATEDIFF 3 次,如下所示。

SELECT CONCAT (
        (DATEDIFF(HOUR, StartDate, EndDate) - 
        (DATEDIFF(HOUR, StartDate, EndDate) % 24)) / 24,
        ' days, ',
        DATEDIFF(HOUR, StartDate, EndDate) % 24,
        ' hours')
FROM RecordsTable

是否可以直接使用内置 SQL 命令将小时数格式化为天数和小时数,或者如果失败,则将 select (datediff(hour, StartDate, EndDate) 格式化为我可以在单次选择中重复使用的变量?

编辑 - 正如建议的那样,解决方案是使用 CTE,如下所示:

WITH totalhours (htotal) AS 
(
    SELECT 
        DATEDIFF(HOUR, StartDate, EndDate) AS htotal
    FROM 
        RecordsTable
)
SELECT 
    CONCAT ((htotal - (htotal % 24)) / 24,
            ' days, ',
            htotal % 24,
            ' hours')
FROM 
    RecordsTable;

【问题讨论】:

  • 您可以使用 CTE 获取一次日期差异。然后从 CTE 中选择一条 SQL 语句,因为它作为一条语句执行。或者在recordstable上使用子查询来获取datediff一次......
  • 成功了 - 你能发帖作为答案,我会接受吗?

标签: sql-server


【解决方案1】:

使用 CTE 生成一次总数,然后在您的选择中参考 CTE 的总数。或者使用子查询生成总数一次,然后从子查询中选择得到想要的结果。

根本问题是您需要将总数具体化一次才能引用它;强制引擎实现一个值通常是通过 CTE 或子查询来完成的。

【讨论】:

  • 这是我第一次在 MSSQL 上解决这些问题。我在 Oracle 上做过类似的工作,但我并没有受到同样的限制,并且能够使用用户创建的函数和存储过程
  • TSQL 有用户函数和存储过程,可以在 T-SQL 中引用。你也可以在这里调用一个函数;但我发现这种方法通常也可以接受;虽然不像函数那样可重用。
  • 限制取决于我正在使用的项目。我最好只创建一个从两个日期返回格式化字符串的函数,但在这种情况下我不允许使用一个。
  • 很高兴我们可以在项目的限制下操作时提供帮助。祝你好运!
  • 非常感谢您的帮助!由于数据库确实很大,我们将所有功能都保留在 .NET 代码中,以便于维护。项目限制有时有点尴尬,但总体而言,限制是有帮助的。
【解决方案2】:

您可以使用datetime 对象和格式字符串或datepart 做很多事情。例如,

declare @n int = 105;
select format(dateadd(day, -1, dateadd(hour, @n, '1753-1-1')), 'd h');
-- 4 9

取最小的datetime 值 (1753-01-01),加上必要的小时数,减去一天(因为在第一天你希望天数 = 0),然后格式化。

您可以像这样改进格式:

select format(dateadd(day, -1, dateadd(hour, @n, '1753-1-1')), 'd \da\y(\s), h \hour(\s)');
-- 4 day(s), 9 hour(s)

当然,这最多只能工作 31 天,因为那时您将离开 1753 年的一月,进入二月。如果是这种情况,请恢复为 datepart。这更丑陋,但适用于更大的值

select 
   datepart(day, (dateadd(day, -1, dateadd(hour, @n, '1753-1-1')))),
   datepart(hour, (dateadd(day, -1, dateadd(hour, @n, '1753-1-1'))));

【讨论】:

  • 我刚刚玩过这个,遗憾的是我不得不坚持使用datepart 解决方案,因为许多日期都超过了一个日历月。但是我导出了格式化日期,我仍然需要使用 CTE,因为它必须在查询的其余部分中的多个点被引用。为了简洁起见,我的示例中的那个被截断了。
猜你喜欢
  • 2017-08-16
  • 2017-12-09
  • 2021-05-22
  • 1970-01-01
  • 2022-01-11
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
相关资源
最近更新 更多