This is the code that is supposed to return an html report by and ssms job.
DECLARE @DataInicialMesAnterior DATE, @DataFinalMesAnterior DATE;
SET @DataInicialMesAnterior = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0);
SET @DataFinalMesAnterior = DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0));
DECLARE @tableHTML2 NVARCHAR(MAX), @corpo2 AS NVARCHAR(50);
SET @tableHTML2 =
N'<font size="1"><H1>Produção Mensal Tecelagem Entre ' + CONVERT(VARCHAR, @DataInicialMesAnterior, 104) + ' - ' + CONVERT(VARCHAR, @DataFinalMesAnterior, 104) + ' </H1> ' +
N'<style> th {color:#FFFFFF; background-color: #6193AC } </style>' +
N'<table border="1" cellpadding="3" cellspacing="0" style="width: 100%">' +
N'<tr><th rowspan="3">Maquina</th><th rowspan="3">Artigo</th><th rowspan="3">Descrição</th><th rowspan="3">Total Metros</th><th rowspan="3">Total Kgs</th></tr>' +
N'<tr></tr><tr><th></th></tr>' +
CAST((
WITH ProductionData AS (
SELECT
'Tear - ' + LTRIM(RTRIM(STR(cast(substring(BI.U_MED1, 2, 2) as int)))) as td,
BI.REF as td1,
ISNULL(ST.design, '') as td2, --design
SUM(CASE WHEN stobs.u_dobramal=1 THEN BI.QTT*2 ELSE bi.qtt END) as 'Metros Produzidos', -- Soma de metros por tear e ref
SUM(CAST(BI.U_MED3 as float)) as 'Kgs Produzidos' -- Soma de kgs por tear e ref
FROM carlom.dbo.BI bi (nolock)
LEFT JOIN carlom.dbo.st ST (nolock) ON ST.ref = BI.REF
INNER JOIN carlom.dbo.stobs stobs (nolock) ON st.ref = stobs.ref
WHERE BI.NDOS = 20
AND BI.u_data2 BETWEEN @DataInicialMesAnterior AND @DataFinalMesAnterior
GROUP BY 'Tear - ' + LTRIM(RTRIM(STR(cast(substring(BI.U_MED1, 2, 2) as int)))), BI.REF, ST.design
), Totals AS (
SELECT
td,
td1,
MAX(td2) as td2,
SUM([Metros Produzidos]) as 'Metros Produzidos',
SUM([Kgs Produzidos]) as 'Kgs Produzidos'
FROM ProductionData
GROUP BY td, td1
HAVING SUM([Metros Produzidos]) > 0 OR SUM([Kgs Produzidos]) > 0
), AllData AS (
SELECT
td,
td1,
MAX(td2) as td2,
SUM([Metros Produzidos]) as 'Metros Produzidos',
SUM([Kgs Produzidos]) as 'Kgs Produzidos'
FROM Totals
GROUP BY td, td1
HAVING SUM([Metros Produzidos]) > 0 OR SUM([Kgs Produzidos]) > 0
), OrderedData AS (
SELECT
td,
td1,
MAX(td2) as td2,
SUM([Metros Produzidos]) as 'Metros Produzidos',
SUM([Kgs Produzidos]) as 'Kgs Produzidos',
0 as TotalOrder
FROM AllData
GROUP BY td, td1
UNION ALL
SELECT
'Total' as td,
'' as td1,
'' as td2,
SUM([Metros Produzidos]) as 'Metros Produzidos',
SUM([Kgs Produzidos]) as 'Kgs Produzidos',
1 as TotalOrder
FROM AllData
)
SELECT
td,
td1,
MAX(td2) as td2,
MAX([Metros Produzidos]) as 'Metros Produzidos',
MAX([Kgs Produzidos]) as 'Kgs Produzidos'
FROM OrderedData
GROUP BY td, td1, TotalOrder
ORDER BY
CASE WHEN TotalOrder = 1 THEN 1 ELSE 0 END,
CASE WHEN ISNUMERIC(SUBSTRING(td, LEN('Tear - ') + 1, LEN(td))) = 1 THEN CAST(SUBSTRING(td, LEN('Tear - ') + 1, LEN(td)) AS INT) ELSE 99999 END,
td
FOR XML PATH('tr'), TYPE
).value('.', 'NVARCHAR(MAX)')) + N'</font></table>';
SET @corpo2 = 'Produção do Mês';
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'PHC',
@recipients = '[email protected]',
@subject = @corpo2,
@body = @tableHTML2,
@body_format = 'HTML';
the code retrieves the following errors
Msg 156, Level 15, State 1, Line 13
Incorrect syntax near the keyword ‘WITH’.
Msg 319, Level 15, State 1, Line 13
Incorrect syntax near the keyword ‘with’. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
Msg 102, Level 15, State 1, Line 26
Incorrect syntax near ‘,’.
Msg 102, Level 15, State 1, Line 36
Incorrect syntax near ‘,’.
Msg 102, Level 15, State 1, Line 46
Incorrect syntax near ‘,’.
Msg 102, Level 15, State 1, Line 79
Incorrect syntax near ‘)’.
2
Answers
You’ve dumped a bunch of CTE declarations inside a
CAST
function; that isn’t allow. CTEs must be defined at the start of the statement not half way through. YOu also have aCAST
but noAS <Data Type>
clause. I half address that, but you’ll need to add the data type.It seems you just wanted to make sure you get
nvarchar(max)
, butFOR XML
anyway does that if you don’t specify,TYPE
.There are various other issues with the code also:
LEFT JOIN
followed by anINNER JOIN
which is dependent on the former makes no sense: either both should beINNER
or bothLEFT
(or you can nest the join conditions).nolock
, it has serious data integrity implications.Totals
andAllData
are eaxctly the same. There is no further aggregation being done, because they are grouping by the same columns.OrderedData
and theUNION ALL
can also be elided by usingGROUPING SETS
. TheGROUPING()
function will tell you whether the row has been grouped for a column.LTRIM(RTRIM(STR(cast(substring(...) as int))))
is nonsense: integers casted to string don’t need trimming. Futhermore why cast toint
only to cast it back? If you want to make sure it’s anint
without throwing an error, just useTRY_CAST
.TEAR -
onto the value at the beginning, as it’s less efficient for grouping, and you have to query it back out afterwards. Instead tack it on in the final stage.VARCHAR
andNVARCHAR
with a length.''
to quote column names, only[]
.ORDER BY CASE WHEN TotalOrder = 1 THEN 1 ELSE 0 END
just doODRER BY TotalOrder
.EOMONTH
to get the end of a month, and useDATEFROMPARTS
to construct dates. In newer versions you can also useDATETRUNC(month
.