【问题标题】:Trying to create a date field to union two tables试图创建一个日期字段来合并两个表
【发布时间】:2017-01-06 12:31:18
【问题描述】:

我正在尝试将两个数据库放在一个视图中,以显示来自两个系统的发票。

一个表格按日期列出发票(即 1 月的销售额是任何具有 1 月日期的发票),另一个表格按年份和期间列出发票(因此,1 月的销售额是“2017”期间“7” - 与日期无关)。由于第二个系统允许在该期间日期范围之外的期间内过帐发票,因此我尝试使用案例语句从年份/期间字段创建日期字段,以显示与发票相同的销售额系统会。

LedgerYear +
case
when LedgerPeriod = 4 then '-10-01'
when LedgerPeriod = 5 then '-11-01'
when LedgerPeriod = 6 then '-12-01'
when LedgerPeriod = 7 then '-01-01'
when LedgerPeriod = 8 then '-02-01'
when LedgerPeriod = 9 then '-03-01'
when LedgerPeriod = 10 then '-04-01'
when LedgerPeriod = 11 then '-05-01'
when LedgerPeriod = 12 then '-06-01'
when LedgerPeriod = 1 then '-07-01'
when LedgerPeriod = 2 then '-08-01'
when LedgerPeriod = 3 then '-09-01'
end
as 'InvDate',

我得到以下内容..

Error converting data type varchar to numeric.

据推测,LedgerYear 是数字,'-10-01' 等是 varchars。联合中另一个表中的 InvDate 是 'datetime' 格式。

如何使 case 语句的输出为日期时间格式?

【问题讨论】:

标签: sql sql-server sql-server-2012 ssms


【解决方案1】:

我相信你只需要一个cast:

select (cast(LedgerYear as varchar(255)) +
        case . . .
       ) as InvDate

注意事项:

  • + 运算符适用于字符串和数字。当任何参数是数字时,它就是加法。因此需要cast()/convert()
  • 仅对字符串和日期常量使用单引号。不要将它们用作列名。
  • 在 SQL Server 中,您可以将其添加为计算列,因此您只需执行一次计算:

    alter table t add invDate as (cast(Ledgeryear as varchar(255)) + case . . . );

然后,该列在表中可用。

【讨论】:

  • 解决了 - 谢谢!
  • 您可能还想在加入值后将其转换或转换回日期格式
【解决方案2】:

除了建议CASTCONVERT 的其他答案之外,您还可以使用CONCAT 函数连接字符串和数字类型值,该函数将根据需要隐式转换任何非字符串类型参数(其中隐式转换是可能的):

SELECT
    CONCAT( LedgerYear, 
            CASE LedgerPeriod
                WHEN 1 THEN '-07-01'
                WHEN 2 THEN '-08-01'
                WHEN 3 THEN '-09-01'
                WHEN 4 THEN '-10-01'
                WHEN 5 THEN '-11-01'
                WHEN 6 THEN '-12-01'
                WHEN 7 THEN '-01-01'
                WHEN 8 THEN '-02-01'
                WHEN 9 THEN '-03-01'
                WHEN 10 THEN '-04-01'
                WHEN 11 THEN '-05-01'
                WHEN 12 THEN '-06-01'
            END
          ) AS InvDate,
FROM someTable

我将您的 CASE 语句从 searched CASE 切换到 simple CASE 语句以删除一些重复,您同样可以使用 CHOOSE 进一步简化,按照 Prdp 的回答: em>

SELECT
    CONCAT( LedgerYear, 
            CHOOSE( @LedgerPeriod, '-07-01',
                                   '-08-01',
                                   '-09-01',
                                   '-10-01',
                                   '-11-01',
                                   '-12-01',
                                   '-01-01',
                                   '-02-01',
                                   '-03-01',
                                   '-04-01',
                                   '-05-01',
                                   '-06-01')
          ) AS InvDate,
FROM someTable

但是,您可能会更轻松地实现您想要做的事情:

SELECT
CAST(
    CAST(@LedgerYear AS VARCHAR(4)) +
    RIGHT('0' + CAST(CASE WHEN @LedgerPeriod <= 6 
                          THEN @LedgerPeriod + 6 
                          ELSE (@LedgerPeriod + 6) % 12 
                      END AS VARCHAR(2)), 2) +
    '01' 
AS DATETIME) AS columnName
FROM someTable

(可能还有一种更优雅的方式将您的经期数字转换为月份数字)

这为您提供了一个实际的DATETIME 字段,您可以选择使用CONVERTFORMAT 以任何您喜欢的方式呈现:

DECLARE @LedgerYear INT = 2016
DECLARE @LedgerPeriod INT = 4
DECLARE @LedgerDate DATETIME

SELECT @LedgerDate =
    CAST(
        CAST(@LedgerYear AS VARCHAR(4)) +
        RIGHT('0' + CAST(CASE WHEN @LedgerPeriod <= 6 
                              THEN @LedgerPeriod + 6 
                              ELSE (@LedgerPeriod + 6) % 12 
                          END AS VARCHAR(2)), 2) +
        '01' 
    AS DATETIME) 

SELECT CONVERT(VARCHAR,@LedgerDate,101) -- U.S. (slashes)
SELECT CONVERT(VARCHAR,@LedgerDate,110) -- USA (hyphens)
SELECT CONVERT(VARCHAR,@LedgerDate,103) -- British/French (slashes)

SELECT FORMAT(@LedgerDate, 'd', 'en-US') -- US English
SELECT FORMAT(@LedgerDate, 'D', 'en-US') -- US English verbose
SELECT FORMAT(@LedgerDate, 'd', 'en-GB') -- British English
SELECT FORMAT(@LedgerDate, 'D', 'en-GB') -- British English verbose

SELECT FORMAT(@LedgerDate, 'dd_|_MM_|_yyyy') -- Custom format

请记住,根据 MSDN:

FORMAT 依赖于 .NET Framework 公共语言运行时 (CLR)。

【讨论】:

    【解决方案3】:

    如果你使用的是 sql server 2012+ 那么你可以使用 CONCATChoose 函数

    select concat(LedgerYear , choose(LedgerPeriod,'-07-01',
                                                   '-08-01',
                                                   '-09-01',
                                                   '-10-01',
                                                   '-11-01',
                                                   '-12-01',
                                                   '-01-01',
                                                   '-02-01',
                                                   '-03-01',
                                                   '-04-01',
                                                   '-05-01',
                                                   '-06-01')) as  'InvDate'
    

    CONCAT 进行隐式转换

    【讨论】:

    • 我从来没有遇到过CHOOSE,知道有用,谢谢!
    猜你喜欢
    • 2014-06-19
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 2019-04-30
    • 2019-03-04
    相关资源
    最近更新 更多