Как объявить расширенный запрос SQL в C#? - PullRequest
0 голосов
/ 06 апреля 2020

У меня проблема с получением результата этого SQL запроса. Это дает результат другими инструментами, но я не могу объявить его в C#. У меня не было проблем с простыми запросами без DECLARE, SET et c ...

Запрос в SQL:

DECLARE @SelectCols nvarchar(MAX),
        @Cols nvarchar(MAX),
        @Query nvarchar(MAX),
        @MinDate date = '2020-03-01',
        @MaxDate date = '2020-03-07'

SET @SelectCols = STUFF((SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
        ',ISNULL(' + QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20)))+',0) AS '+QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20)))
FROM    sys.all_objects a CROSS JOIN sys.all_objects b
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET     @Cols = STUFF((SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
                ',' + QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20)))
                FROM    sys.all_objects a CROSS JOIN sys.all_objects b
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET @Query ='DECLARE @MinDate1 DATE = ''' + CAST(@MinDate AS varchar(20)) +'''
            DECLARE @MaxDate1 DATE = ''' +CAST(@MaxDate AS varchar(20)) + '''
            SELECT FIRMA,' + @SelectCols + ' FROM
            (
                SELECT Shortcut as FIRMA, cast(mg.data as date) as DATA, CAST(ABS(SUM(mg.wartoscWz)) as decimal(20,2)) as WART
                FROM HM.MG
                INNER JOIN SSCommon.STContractors STC ON MG.khid = STC.id
                WHERE MG.subtyp = 89
                AND MG.aktywny = 1
                AND MG.anulowany = 0
                AND MG.bufor = 0
                AND MG.kod like ''%PZ''
                AND MG.typ_dk <> ''SrT''
                AND MG.createdDate >= @MinDate1 and MG.createdDate < DATEADD(day, 1, @MaxDate1)
                Group by (Shortcut), mg.data
            ) DANE
            PIVOT
            (
            max(WART) FOR [DATA] IN ( ' +@cols+ ')
            ) p
            ORDER BY FIRMA
            '
Execute(@query)

Этот запрос работает, но мое объявление в C# не работает, и я не могу найти ошибку, или я сделал что-то не так.

String sql = @"DECLARE @SelectCols nvarchar(MAX), @Cols nvarchar(MAX), @Query nvarchar(MAX), "
    + "@MinDate date = '" +parametra + "', "
    + "@MaxDate date = '" + parametrb + "' "
    + "SET @SelectCols = STUFF((SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1) "
    + "',ISNULL(' + QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20)))+',0) AS '+QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20))) "
    + "FROM sys.all_objects a CROSS JOIN sys.all_objects b "
    + "FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'') "
    + "SET @Cols = STUFF((SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1) "
    + "',' + QUOTENAME(CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20))) "
    + "FROM sys.all_objects a CROSS JOIN sys.all_objects b "
    + "FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'') "
    + "SET @Query ='DECLARE @MinDate1 DATE = ''' + CAST(@MinDate AS varchar(20)) +'''"
    + "DECLARE @MaxDate1 DATE = ''' +CAST(@MaxDate AS varchar(20)) + ''' "
    + "SELECT FIRMA,' + @SelectCols + ' FROM "
    + "( "
    + "SELECT Shortcut as FIRMA, cast(mg.data as date) as DATA, CAST(ABS(SUM(mg.wartoscWz)) as decimal(20, 2)) as WART "
    + "FROM HM.MG "
    + "INNER JOIN SSCommon.STContractors STC ON MG.khid = STC.id "
    + "WHERE MG.subtyp = 89 "
    + "AND MG.aktywny = 1 "
    + "AND MG.anulowany = 0 "
    + "AND MG.bufor = 0 "
    + "AND MG.kod like ''%PZ'' "
    + "AND MG.typ_dk <> ''SrT'' "
    + "AND MG.createdDate >= @MinDate1 and MG.createdDate < DATEADD(day, 1, @MaxDate1) "
    + "Group by (Shortcut), mg.data "
    + ") DANE "
    + "PIVOT "
    + "( "
    + "max(WART) FOR [DATA] IN ( ' +@cols+ ') "
    + ") p "
    + "ORDER BY FIRMA "
    + "Execute(@query)";

Ответы [ 2 ]

1 голос
/ 06 апреля 2020

Как уже отмечали другие, произошла синтаксическая ошибка. Но эта ошибка была вызвана встраиванием SQL в C# наихудшим из возможных способов. Просто вставьте его в многострочный дословный строковый литерал.

например

        var sql = @"
DECLARE @SelectCols nvarchar(MAX),
        @Cols nvarchar(MAX),
        @Query nvarchar(MAX),
        @MinDate date = '2020-03-01',
        @MaxDate date = '2020-03-07'

SET @SelectCols = STUFF((SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
        ',ISNULL(' + QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20)))+',0) AS '+QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20)))
FROM    sys.all_objects a CROSS JOIN sys.all_objects b
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET     @Cols = STUFF((SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
                ',' + QUOTENAME (CAST(DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)AS varchar(20)))
                FROM    sys.all_objects a CROSS JOIN sys.all_objects b
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET @Query ='DECLARE @MinDate1 DATE = ''' + CAST(@MinDate AS varchar(20)) +'''
            DECLARE @MaxDate1 DATE = ''' +CAST(@MaxDate AS varchar(20)) + '''
            SELECT FIRMA,' + @SelectCols + ' FROM
            (
                SELECT Shortcut as FIRMA, cast(mg.data as date) as DATA, CAST(ABS(SUM(mg.wartoscWz)) as decimal(20,2)) as WART
                FROM HM.MG
                INNER JOIN SSCommon.STContractors STC ON MG.khid = STC.id
                WHERE MG.subtyp = 89
                AND MG.aktywny = 1
                AND MG.anulowany = 0
                AND MG.bufor = 0
                AND MG.kod like ''%PZ''
                AND MG.typ_dk <> ''SrT''
                AND MG.createdDate >= @MinDate1 and MG.createdDate < DATEADD(day, 1, @MaxDate1)
                Group by (Shortcut), mg.data
            ) DANE
            PIVOT
            (
            max(WART) FOR [DATA] IN ( ' +@cols+ ')
            ) p
            ORDER BY FIRMA
            '
Execute(@query)
";
0 голосов
/ 06 апреля 2020

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

В действительности не имеет смысла использовать T SQL для создания динамического c SQL запроса здесь. В C# будет гораздо меньше беспорядка, как показано ниже

            DateTime minDate = DateTime.Parse("2020-03-01");
            DateTime maxDate = DateTime.Parse("2020-03-07");

            //array of strings in format "[2020-03-01]" covering whole date range
            var pivotColumns =
                Enumerable.Range(0, 1 + maxDate.Subtract(minDate).Days)
                .Select(offset => minDate.AddDays(offset).ToString("[yyyy-MM-dd]"))
                .ToArray();

            //enumerable of strings in format "ISNULL([2020-03-01], 0) AS [2020-03-01]"
            var selectColumns = pivotColumns.Select(pc => "ISNULL(" + pc + ", 0) AS " + pc);

            string query = @"
SELECT FIRMA,
       " + string.Join(",", selectColumns) + @"
FROM   (SELECT Shortcut                                       AS FIRMA,
               CAST(mg.data AS DATE)                          AS DATA,
               CAST(ABS(SUM(mg.wartoscWz)) AS DECIMAL(20, 2)) AS WART
        FROM   HM.MG
               INNER JOIN SSCommon.STContractors STC
                       ON MG.khid = STC.id
        WHERE  MG.subtyp = 89
               AND MG.aktywny = 1
               AND MG.anulowany = 0
               AND MG.bufor = 0
               AND MG.kod LIKE '%PZ'
               AND MG.typ_dk <> 'SrT'
               AND MG.createdDate >= @MinDate
               AND MG.createdDate < DATEADD(day, 1, @MaxDate)
        GROUP  BY ( Shortcut ),
                  mg.data) DANE
       PIVOT ( MAX(WART)
             FOR [DATA] IN ( " + string.Join(",", pivotColumns) + @") ) p
ORDER  BY FIRMA 
";

            //TODO: Execute query and pass @MinDate/@MaxDate as parameters
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...