试图创建一个日期字段来合并两个表

Trying to create a date field to union two tables

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

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

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。联合中另一个 table 中的 InvDate 是 'datetime' 格式。

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

我相信你只需要一个cast:

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

备注:

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

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

然后,该列在 table 中可用。

如果您使用的是 sql 服务器 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 进行隐式转换

除了建议 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 的回答进行简化:

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 字段,您可以使用 CONVERT or FORMAT:

选择以任何您喜欢的方式呈现
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 relies on the presence of .the .NET Framework Common Language Runtime (CLR).