【问题标题】:sql server lead - problems with datesql server Lead - 日期问题
【发布时间】:2014-05-27 11:57:33
【问题描述】:

我对 sql server 2012 中新的铅 olap 函数有问题。

CREATE TABLE Atext (id int, bez varchar(10), von date); 

GO

INSERT INTO Atext VALUES (1, 't1', '2001-01-01'), (1, 't2', '2012-01-01'), (2, 'a1', '2020-01-01'), (2,'a1' , '2030-01-01'), (2, 'b', '2040-05-01'), (2, 'a3', '2989-05-01'); 
GO

SELECT 
        id, 
        bez, 
        von,
        lead(von,1,0) over (partition by id ORDER BY von) -1 as bis
FROM 
        Atext
order by 
        id, 
        Von

选择查询抛出错误:

Msg 206, Level 16, State 2, Line 1 
Operand type clash: int is incompatible with date

为什么对数据类型日期时间有限制?

我知道一种解决方法,但不是很好:

SELECT
    id,
    bez,
    CAST(vonChar AS DATE) AS Von,
    CASE
        WHEN bisChar <> '0'
        THEN (DATEADD(DAY,-1,(CAST((
                    CASE
                        WHEN bisChar <> '0'
                        THEN vonChar
                        ELSE NULL
                    END)AS DATE)) ))
        ELSE NULL /*'9999-12-31'*/
    END AS Bis
FROM
    (
        SELECT
            id,
            bez,
            vonChar ,
            lead(vonChar,1,0) over (partition BY id ORDER BY vonChar) AS bisChar
        FROM
            (
                SELECT
                    id,
                    bez,
                    CAST(von AS VARCHAR(10)) vonChar
                FROM
                    Atext) tab ) tab2
ORDER BY
    id,
    Von

Microsoft SQL Server 2012 (SP1) - 11.0.3128.0 (X64)

【问题讨论】:

    标签: sql sql-server date lead


    【解决方案1】:

    使用日期(或可以隐式转换为日期的东西)作为前导函数的默认值,DATEADD 函数将是一个更简单的解决方法:

    SELECT 
            id, 
            bez, 
            von,
            DATEADD(DAY, -1, LEAD(von, 1, '19000101') 
                            OVER (PARTITION BY id ORDER BY von)) AS bis
    FROM Atext
    ORDER BY id, Von;
    

    或者只是不打扰默认值。不需要:

    SELECT 
            id, 
            bez, 
            von,
            DATEADD(DAY, -1, LEAD(von, 1) 
                            OVER (PARTITION BY id ORDER BY von)) AS bis
    FROM Atext
    ORDER BY id, Von;
    

    问题是您不能将INT 转换为DATE。在 SQL Server 的表达式中,表达式的所有部分都必须是相同的数据类型,因此,例如:

    SELECT TOP 1 GETDATE() + number
    FROM master..spt_values
    WHERE type = 'p'
    

    在幕后 SQL Server 需要决定是否将 GETDATE() 转换为整数,以便表达式的所有部分都是整数,或者将 1 转换为日期时间,以便 所有部分都是日期时间。 SQL Server 的Data Type Precedence 规定 DATETIME 的优先级高于 INT,因此 SQL Server 将 1 转换为 datetime,这可以在执行计划中看到:

    <ScalarOperator ScalarString="getdate()+[Expr1005]">
    ....
    <ColumnReference Column="Expr1005" />
    <ScalarOperator ScalarString="CONVERT_IMPLICIT(datetime,[master].[dbo].[spt_values].[number],0)">
    

    这表明 INT 列 master..spt_values.number 在添加到 getdate() 之前已隐式转换为日期时间

    无论出于何种原因(不久前我进行了广泛研究,但没有找到确切解释原因),从 int 到 date 没有隐式或显式转换,您必须使用 date 函数。

    【讨论】:

      【解决方案2】:

      与所有其他答案相同,但以 DATEADD 作为主要参数:

      SELECT
        id, 
        bez,
        von,
        lead(DATEADD(DAY,-1, von),1, null) over (partition by id order by von)
      from 
        Atext
      order by
          id,
          Von
      

      SQLFiddle 示例

      【讨论】:

        【解决方案3】:

        您可以在此查询中使用 DATEADD()。此外,数据类型的 LEAD 的默认值不能为 0,因此我将其更改为 NULL,或者您可以使用任何 DATE 常量。

        SELECT 
                id, 
                bez, 
                von,
                DATEADD(DAY,-1,lead(von,1,NULL) 
                               over (partition by id ORDER BY von)) as bis
        FROM 
                Atext
        order by 
                id, 
                Von
        

        SQLFiddle demo

        【讨论】:

          【解决方案4】:

          这对您有帮助吗,当在预期日期字段的位置给出 0 时发生错误。

          I replaced lead(von,1,0) with lead(von,1,'1900-01-01')
          

          查看另一个具有相同结果的代码。

          SET DATEFORMAT ymd
          DECLARE @Atext TABLE  
              (id INT, bez VARCHAR(10), von DATE); 
          
          INSERT INTO @Atext VALUES 
              (1, 't1', '2001-01-01'),
              (1, 't2', '2012-01-01'), (2, 'a1', '2020-01-01'), 
              (2,'a1' , '2030-01-01'), (2, 'b', '2040-05-01'),
              (2, 'a3', '2099-05-01'); 
          
          SELECT  id, 
                  bez, 
                  von,
                  lead(von,1,'1900-01-01') OVER (PARTITION BY id ORDER BY von) AS bis
          FROM    @Atext
          ORDER   by 
                  id, 
                  Von
          

          结果

          【讨论】:

            猜你喜欢
            • 2016-03-24
            • 2021-11-03
            • 1970-01-01
            • 1970-01-01
            • 2023-01-18
            • 2019-08-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-28
            相关资源
            最近更新 更多