7

SQL Server 2012 の新しい Lead 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

データ型 datetime に関して制限があるのはなぜですか?

私は回避策を知っていますが、あまり良くありません:

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)

4

4 に答える 4

3

リード関数のデフォルトとして日付 (または日付に暗黙的にキャストできるもの) を使用すると、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 ServerGETDATE()は、式のすべての部分が整数になるように整数に変換するか1、すべての部分が日時になるように日時に変換するかを決定する必要があります。SQL Server のデータ型の優先順位は、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 への暗黙的または明示的な変換はなく、日付関数を使用する必要があります。

于 2014-05-27T12:06:13.053 に答える
2

このクエリでは 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

于 2014-05-27T12:07:02.693 に答える
0

これは役に立ちますか? 日付フィールドが予期される場所に 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

結果

ここに画像の説明を入力

于 2014-05-27T12:23:04.163 に答える