Несовместимость типов данных в моем скрипте Dynamic Pivot - PullRequest
0 голосов
/ 01 ноября 2018

, поэтому я работал над сценарием динамического разворота, и я почти заставил его работать, но у меня проблемы с объявленными переменными. Вот мой код:

DECLARE @start_date DATE
DECLARE @end_date DATE

SET @start_date = CAST(DATEADD(dd,((DATEDIFF(dd,'17530101',GETDATE())/7)*7)-7,'17530101') AS DATE)
SET @end_date = CAST(DATEADD(dd,((DATEDIFF(dd,'17530101',GETDATE())/7)*7)-1,'17530101') AS DATE)

DECLARE @cols  AS NVARCHAR(MAX)='';
DECLARE @query AS NVARCHAR(MAX)='';

SELECT @cols = @cols + QUOTENAME(TicketDate) + ',' 
FROM 
    (SELECT DISTINCT TOP 14 ad.TicketDate 
    FROM AttendDet ad 
    WHERE CAST(ad.TicketDate AS DATE) BETWEEN  @start_date AND @end_date 
        AND ad.EmplCode IS NOT NULL 
    ORDER BY ad.TicketDate) as dates

SELECT @cols = SUBSTRING(@cols, 0, LEN(@cols)) 

SET @query =
'SELECT * FROM
(
    SELECT
        CAST(ad.EmplName AS NVARCHAR(MAX)) AS [EmplName],
        CAST(ad.TicketDate AS DATE) AS [TicketDate],
        ROUND(ad.TotActTime, 2) AS [TotalHrs]
    FROM AttendDet ad
    WHERE ad.EmplCode IS NOT NULL
        AND ad.AttendCode <> 9999
        AND CAST(ad.TicketDate AS DATE) BETWEEN (' + @start_date + ') AND (' + @end_date + ')
) basedata
PIVOT
(
    SUM(TotalHrs) FOR TicketDate IN (' + @cols + ')
) piv'

EXECUTE(@query)

Вот строка, которая вызывает ошибку:

 AND CAST(ad.TicketDate AS DATE) BETWEEN (' + @start_date + ') AND (' + @end_date + ')

Я получаю ошибку: «Типы данных varchar и date несовместимы в операторе добавления». Я попытался изменить типы данных на VARCHAR, но это не сработало, когда я сделал это, я получил эту ошибку: Ошибка преобразования при преобразовании даты и / или времени из строки символов.

Я знаю, что я в правильном направлении, потому что, если я вручную укажу эту строку, например:

AND CAST(ad.TicketDate AS DATE) BETWEEN ''10/22/18'' AND ''10/28/18''

Это работает отлично, как и ожидалось, но я, очевидно, не хочу этого делать, так как это разрушит всю цель сценария. Все это должно работать до тех пор, пока установлены @start_data и @end_date, но я застрял на том, как это закончить. За последний час я пробовал все что угодно и не могу понять

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 01 ноября 2018

Вам нужно привести его к varchar, потому что здесь SQL интерпретирует + как сложение против конкатенации.

DECLARE @start_date DATE = getdate()
DECLARE @end_date DATE = getdate()
DECLARE @cols varchar(10) = ''
DECLARE @query varchar(max)

SET @query =
'SELECT * FROM
(
    SELECT
        CAST(ad.EmplName AS NVARCHAR(MAX)) AS [EmplName],
        CAST(ad.TicketDate AS DATE) AS [TicketDate],
        ROUND(ad.TotActTime, 2) AS [TotalHrs]
    FROM AttendDet ad
    WHERE ad.EmplCode IS NOT NULL
        AND ad.AttendCode <> 9999
        AND CAST(ad.TicketDate AS DATE) BETWEEN ''' + cast(@start_date as varchar) + ''' AND ''' + cast(@end_date as varchar) + '''
) basedata
PIVOT
(
    SUM(TotalHrs) FOR TicketDate IN (' + @cols + ')
) piv'

print @query

Итак, ваш запрос будет таким. Обратите внимание, что я изменил команду на печать вместо выполнения, чтобы вы могли видеть, как она выглядит:

DECLARE @start_date DATE
DECLARE @end_date DATE

SET @start_date = CAST(DATEADD(dd,((DATEDIFF(dd,'17530101',GETDATE())/7)*7)-7,'17530101') AS DATE)
SET @end_date = CAST(DATEADD(dd,((DATEDIFF(dd,'17530101',GETDATE())/7)*7)-1,'17530101') AS DATE)

DECLARE @cols  AS NVARCHAR(MAX)='';
DECLARE @query AS NVARCHAR(MAX)='';

SELECT @cols = @cols + QUOTENAME(TicketDate) + ',' 
FROM 
    (SELECT DISTINCT TOP 14 ad.TicketDate 
    FROM AttendDet ad 
    WHERE CAST(ad.TicketDate AS DATE) BETWEEN  @start_date AND @end_date 
        AND ad.EmplCode IS NOT NULL 
    ORDER BY ad.TicketDate) as dates

SELECT @cols = SUBSTRING(@cols, 0, LEN(@cols)) 

SET @query =
'SELECT * FROM
(
    SELECT
        CAST(ad.EmplName AS NVARCHAR(MAX)) AS [EmplName],
        CAST(ad.TicketDate AS DATE) AS [TicketDate],
        ROUND(ad.TotActTime, 2) AS [TotalHrs]
    FROM AttendDet ad
    WHERE ad.EmplCode IS NOT NULL
        AND ad.AttendCode <> 9999
        AND CAST(ad.TicketDate AS DATE) BETWEEN ''' + cast(@start_date as varchar) + ''' AND ''' + cast(@end_date as varchar) + '''
) basedata
PIVOT
(
    SUM(TotalHrs) FOR TicketDate IN (' + @cols + ')
) piv'

--EXECUTE(@query)
print @query
0 голосов
/ 01 ноября 2018

У вас есть несколько вариантов.

  1. Используя оператор + для объединения строк, все значения должны быть самими строками, и вы не можете неявно преобразовать DATE в строку, как говорится в ваших сообщениях об ошибках. Вы можете, однако, обернуть обе переменные даты явным CAST с или CONVERT с, если это ваша сумка:

    (' + CAST(@start_date AS VARCHAR(10)) + ') AND (' + CAST(@end_date AS VARCHAR(10)) + ')

  2. Если ваша версия поддерживает это (2012+), просто используйте CONCAT . Он заботится о преобразованиях для вас.

    SET @query = CONCAT( 'SELECT * FROM ( SELECT CAST(ad.EmplName AS NVARCHAR(MAX)) AS [EmplName], CAST(ad.TicketDate AS DATE) AS [TicketDate], ROUND(ad.TotActTime, 2) AS [TotalHrs] FROM AttendDet ad WHERE ad.EmplCode IS NOT NULL AND ad.AttendCode <> 9999 AND CAST(ad.TicketDate AS DATE) BETWEEN (', @start_date, ') AND (', @end_date, ') ) basedata PIVOT ( SUM(TotalHrs) FOR TicketDate IN (', @cols, ') ) piv' )

0 голосов
/ 01 ноября 2018

Это должно работать:

    AND CAST(ad.TicketDate AS DATE) BETWEEN (' + CONVERT(varchar(11),@start_date,101) + ') AND (' + CONVERT(varchar(11),@end_date,101) + ')
...