简体   繁体   中英

How to declare advanced SQL query in C#?

I have a problem with getting result of this SQL query. It gives result by other tools, but I can't declare it in C#. I didn't have problems with easy queries without DECLARE , SET etc...

Query in 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)

This query is working, but my declaration in C# is not working and I cannot find bug or I made something wrong.

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)";

As others have noted there was a syntax error. But that error was caused by embedding SQL in C# in the worst possible way. Just paste it into a multi-line verbatim string literal.

eg

        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)
";

Your problem is a missed quote. You didn't spot this yourself as the code is an unreadable mess.

It doesn't really make sense to use TSQL to build up the dynamic SQL query here anyway. It will be much less messy to do it in C# as below

            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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM