查询以将计数转换为百万或数千

Nil*_*esh 5 sql-server sql-server-2008-r2 type-conversion

我正在对数据库运行查询以返回计数(*)的行数。

  • 如果计数大于百万,比如说 2,250,304,我希望查询返回 2.25M。
  • 如果计数大于 1000 但小于一百万,比如 65130,我希望查询返回“65.1k”。
  • 如果计数小于 1000,则查询应返回实际计数。

这是我的查询:

SELECT DATENAME(mm, CREATEDTS) + ', ' + DATENAME(yyyy, CREATEDTS) AS Month,
       CASE
         WHEN count(*) > 1000
              AND count(*) < 1000000 THEN ( CONVERT (VARCHAR(10), ( count(*) / 1000 )) ) + 'k'
         WHEN count(*) > 1000000 THEN ( CONVERT (VARCHAR(10), ( count(*) / 1000 )) ) + 'm'
         ELSE COUNT(*)
       END
FROM   USAGEDATA
GROUP  BY month(CREATEDTS),
          DATENAME(mm, CREATEDTS) + ', ' + DATENAME(yyyy, CREATEDTS)
ORDER  BY MONTH(CREATEDTS) 
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我收到一个错误:

将 varchar 值“165k”转换为数据类型 int 时,消息 245,级别 16,状态 1,第 1 行转换失败。

我不确定在哪里将 varchar 转换为 INT 并收到此错误。

Mar*_*ith 7

如果可能,这种类型的格式化通常最好在您的应用程序中完成。

问题是case 表达式根据任何分支的最高数据类型优先级返回结果。

所以,你需要投最后COUNT你支CASEVARCHAR过的int优先级高于varchar

此外,您可能应该将年份添加到您的订单中,除非您确实想同时订购 2014 年 1 月和 2015 年 1 月,然后是 2 月等。

虽然我可能很想把那个连接的字符串GROUP BY也去掉并重写它(在此过程中修复了整数除法和不一致的边界条件的其他几个问题)作为。

WITH T(mmmyyyy, FORMATTED_COUNT, Yr, Mnth)
     AS (SELECT DATENAME(MONTH, MIN(CREATEDTS)) + ', ' + DATENAME(YEAR, MIN(CREATEDTS)) AS Month,
                CASE
                  WHEN COUNT(*) BETWEEN 1000 AND 999999
                    THEN ( CONVERT (VARCHAR(10), ( CAST(ROUND(COUNT(*) / 1000.0, 1) AS NUMERIC(4, 1)) )) ) + 'k'
                  WHEN COUNT(*) >= 1000000
                    THEN ( CONVERT (VARCHAR(10), ( CAST(ROUND(COUNT(*) / 1000000.0, 2) AS NUMERIC(6, 2)) )) ) + 'm'
                  ELSE CONVERT (VARCHAR(10), COUNT(*))
                END,
                YEAR(CREATEDTS),
                MONTH(CREATEDTS)
         FROM   USAGEDATA
         GROUP  BY YEAR(CREATEDTS),
                   MONTH(CREATEDTS))
SELECT mmmyyyy,
       FORMATTED_COUNT
FROM   T
ORDER  BY Yr,
          Mnth; 
Run Code Online (Sandbox Code Playgroud)