SQL Server With CTE variable not accepting - sql

With CTE if i assign the variable outside and call the varibale inside the table not accepting the variable but if i pass the value directly inside the CTE query return the value.
DECLARE #dates datetime = '8/5/2019 12:41:55 PM',
#Staff nvarchar(250) = N'staff1';
WITH
CTE AS
(SELECT DI.SchedulerID,
DI.CustID,
ORC.CustomerName,
(SELECT CONVERT(char(5), DI.InTime, 108) AS [time]) AS InTime,
DI.Identifier,
DI.PictureUploaded,
(SELECT CONVERT(char(5), DO.OutTime, 108) AS [time]) AS OutTime,
CONCAT((DATEDIFF(MINUTE, DI.InTime, DO.OutTime) / 60), ':', (DATEDIFF(MINUTE, DI.InTime, DO.OutTime) % 60)) AS SpendInMinutes,
ROW_NUMBER() OVER (PARTITION BY DI.SchedulerID,
ORC.CustomerName
ORDER BY DI.SchedulerID DESC) AS RN
FROM [ServiceUsers].[dbo].[DeliveryIn] DI
INNER JOIN [Distribution].dbo.ORCustomerList ORC ON DI.CustID = ORC.CustID
INNER JOIN [ServiceUsers].[dbo].[DeliveryOut] DO ON DI.SchedulerID = DO.SchedulerID
WHERE (SELECT CONVERT(date, DI.InDate)) = (SELECT #dates)
AND DI.CreatedBy = (SELECT #Staff))
SELECT *
FROM CTE
WHERE RN = 1;
If i pass the values directly to the where it will return the rows.

Note to commenters -- I'm not saying the code is "wrong" and would not run, just that it is strange and not the typical way it would be written
your sql is strange
Where (SELECT CONVERT(date, DI.InDate))=(Select #dates) AND DI.CreatedBy=(Select #Staff)
should be
Where CONVERT(date, DI.InDate)=#dates AND DI.CreatedBy=#Staff
also I would write declare like this
DECLARE #dates datetime;
DECLARE #staff nvarchar(250);
SET #dates='2019-08-05';
SET #Staff=N'staff1';

Related

What does "t=" do in SELECT t = DATEADD(HOUR, n-1, #start) FROM x ORDER BY t;

I've found this article Get every hour for a time range that help me a lot with this code:
DECLARE
#start TIME(0) = '11:00 AM',
#end TIME(0) = '2:00 PM';
WITH x(n) AS
(
SELECT TOP (DATEDIFF(HOUR, #start, #end) + 1)
rn = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_columns ORDER BY [object_id]
)
SELECT t = DATEADD(HOUR, n-1, #start) FROM x ORDER BY t;
But I don't know what 't =' is or does in this select clause.
The same for 'rn = '
What is that? There is a technical name for that? How can I use it?
it sets alias name to field result
SELECT OriginalColumnName as MyFavorityName
FROM MyTableName
it is equal
SELECT MyFavorityName = OriginalColumnName
FROM MyTableName

Use dynamic value to a variable which is being used in the subsequent dynamic query in my code

This code works when set #ToDate = '20200311' i.e. when I have hardcoded the specific date, but does not work when I want this to always execute till the current date
The line set #ToDate = select .....getdate.. throws error, can you please help me out and tell me what I should do to rectify?
While ##Fetchstatus =0,
begin
set #Fromdate = '20180102';
set #ToDate = select convert (varchar, getdate(), 112);
while (#Fromdate < #ToDate) begin
set #StrQuery = 'INSERT into dbo.Tmp_M_Rates (Rate_Date, Rate_D, Entity, cur) values ('
+''''+ CAST (#FromDate AS nvarchar) + ''', ''' + Substring (CONVERT (VARCHAR
(10), #Fromdate, 112),3,8) + ''', ''' + #EntityName + ''', ''' + #Cur +
''')'
EXEC (#StrQuery)
set #Fromdate = dateadd(DAY,1,#Fromdate)
end
If Gordon's answer has the correct idea, a far better approach would be to not use any type of recursion. SQL Server is designed for set based methods, and so you should really be using one.
The method you want here is a Tally, which isn't recursive, and isn't limited to 100 loops by default (like an rCTE) because it doesn't loop:
DECLARE #FromDate date = '20180102';
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (DATEDIFF(DAY,#FromDate, GETDATE())+1)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3), --1000 rows, add more cross joins to N for more rows
Dates AS(
SELECT DATEADD(DAY, T.I, #FromDate) AS D
FROM Tally T)
INSERT INTO dbo.Tmp_M_Rates (Rate_Date, Rate_D, Entity, cur)
SELECT D,
SUBSTRING(CONVERT(VARCHAR(10), #Fromdate, 112), 3, 8),
#EntityName,
#Cur
FROM Dates;
Just another option with an ad-hoc tally/numbers table
Example
Declare #Date1 date = '2018-01-02'
Declare #Date2 date = getdate()
Declare #Entity varchar(50) ='Entity Name'
Declare #Cur varchar(50) ='USD'
--INSERT into dbo.Tmp_M_Rates (Rate_Date, Rate_D, Entity, cur)
Select Rate_Date = D
,Rate_D = dateadd(DAY,1,D)
,Entity = #Entity
,Cur = #Cur
From (
Select Top (DateDiff(DAY,#Date1,#Date2)+1)
D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),#Date1)
From master..spt_values n1,master..spt_values n2
) A
Generates the Following for INSERT
You can phrase this as a single query with no dynamic SQL:
WITH dates as (
SELECT CONVERT(date, '20180102') as dte
UNION ALL
SELECT dateadd(day, 1, dte)
FROM CTE
WHERE dte <= GETDATE()
)
INSERT into dbo.Tmp_M_Rates (Rate_Date, Rate_D, Entity, cur)
SELECT dte, SUBSTRING(CONVERT(VARCHAR(10), #Fromdate, 112), 3, 8),
#EntityName, #Cur
FROM dates
OPTION (MAXRECURSION 0);
I would strongly recommend that you take this or a similar approach.

Date generator to table variable

I read about a way to generate a range of dates: Generate a set or sequence without loops. I'm having trouble with applying the method.
This code successfully generates a table of dates from #Start to #End:
;WITH d([Date]) AS (
SELECT DATEADD(DAY, n-1, #Start)
FROM (
SELECT TOP (DATEDIFF(DAY, #Start, #End) + 1)
ROW_NUMBER() OVER (ORDER BY Number) FROM master..spt_values
) AS x(n)
)
SELECT d.Date
FROM d
I'm fairly new to more advanced SQL so this is quite the black box. But it works. So now I wanted to save the result into a table variable for further processing:
DECLARE #Days TABLE ([Date] DATE NULL, Val INT NULL)
The date will have a value associated with it. However simply inserting into the table seems not to be working. Neither the following or wrapping it in yet another select statement works:
INSERT INTO #Days (Date)
WITH d([Date]) AS (
SELECT DATEADD(DAY, n-1, #Start)
FROM (
SELECT TOP (DATEDIFF(DAY, #Start, #End) + 1)
ROW_NUMBER() OVER (ORDER BY Number) FROM master..spt_values
) AS x(n)
)
SELECT d.Date
FROM d
It seems the 'last statement must be terminated with a semicolon' or an 'incorrect syntax near ;' is thrown depending on the presence of the semicolon.
Do you have any directions? I'm confused like mad.
Your problem is not the CTE, it is the INSERT syntax. As explained in the documentation, the CTE comes before the INSERT:
WITH d([Date]) AS (
SELECT DATEADD(DAY, n-1, #Start)
FROM (
SELECT TOP (DATEDIFF(DAY, #Start, #End) + 1)
ROW_NUMBER() OVER (ORDER BY Number) FROM master..spt_values
) AS x(n)
)
INSERT INTO #Days (Date)
SELECT d.Date
FROM d;

Making SQL query results 'PRINT'?

I have a query which I eventually got to work fine but what I really need is the results to be displayed using the SQL PRINT command. The reason for this is I am automating the results to be emailed, and if I can have them come out as printed text then I can just embed the results in the email using the tool we use here. Otherwise, the current results have to be attached as a file and I would prefer the printed text if possible.
I have tried to modify the query by adding DECLARE and PRINT but I am really confused and can't figure it out. The query has 2 CTE's in it pulling data from multiple databases. What it is doing is selecting all the sale numbers/ID's from our SAP system for yesterday and comparing them with our the Sale numbers/ID's from our POS system for yesterday to make sure every sale in our POS system is now in SAP. The query itself works fine.
How can I print the results of this query?
WITH CTE1 (SAP_SALE)
AS
(
select distinct convert(BIGINT,convert(varchar(15),WERKS)+(select RIGHT(convert(Varchar(20),BONNR),7)))
as Branch_tx_no from [PDP].[pdp].[S120] WITH (NOLOCK)
where SPTAG >= CAST(CONVERT(VARCHAR(10), GETDATE() -1, 101) AS DATETIME) AND
SPTAG < CAST(CONVERT(VARCHAR(10), GETDATE(), 101) AS DATETIME)
),
CTE2 (AR_SALE)
AS
(
select convert(varchar(15),branch_no)+convert(varchar(15),sale_tx_no)
from [ARDB01].[PP_BODATA].[DBO].[sales_tx_hdr] WITH (NOLOCK)
WHERE sale_date >= CAST(CONVERT(VARCHAR(10), GETDATE() -1, 101) AS DATETIME) AND
sale_date < CAST(CONVERT(VARCHAR(10), GETDATE(), 101) AS DATETIME)
and sale_type in ('C','L')
)
SELECT AR_SALE FROM CTE2 AS CTE2
Left OUTER JOIN CTE1 AS CTE1
ON CTE1.SAP_SALE = CTE2.AR_SALE
WHERE CTE1.SAP_SALE IS NULL
ORDER BY CTE2.AR_SALE
The easiest solution is to use a cursor and PRINT one row at a time. Or you could use XML-concatenation, if you do not have any special characters in the result:
DECLARE #txt NVARCHAR(MAX);
WITH CTE1 (SAP_SALE)
AS
(
select distinct convert(BIGINT,convert(varchar(15),WERKS)+(select RIGHT(convert(Varchar(20),BONNR),7)))
as Branch_tx_no from [PDP].[pdp].[S120] WITH (NOLOCK)
where SPTAG >= CAST(CONVERT(VARCHAR(10), GETDATE() -1, 101) AS DATETIME) AND
SPTAG < CAST(CONVERT(VARCHAR(10), GETDATE(), 101) AS DATETIME)
),
CTE2 (AR_SALE)
AS
(
select convert(varchar(15),branch_no)+convert(varchar(15),sale_tx_no)
from [ARDB01].[PP_BODATA].[DBO].[sales_tx_hdr] WITH (NOLOCK)
WHERE sale_date >= CAST(CONVERT(VARCHAR(10), GETDATE() -1, 101) AS DATETIME) AND
sale_date < CAST(CONVERT(VARCHAR(10), GETDATE(), 101) AS DATETIME)
and sale_type in ('C','L')
)
SELECT #txt = (
SELECT CHAR(13)+CHAR(10)+AR_SALE FROM CTE2 AS CTE2
Left OUTER JOIN CTE1 AS CTE1
ON CTE1.SAP_SALE = CTE2.AR_SALE
WHERE CTE1.SAP_SALE IS NULL
ORDER BY CTE2.AR_SALE
FOR XML PATH(''),TYPE
).value('.','NVARCHAR(MAX)');
PRINT #txt;
If you need to use PRINT you can combine results of your query into a comma (or other char) separated VARCHAR variable and then print that variable, e.g.
DECLARE #sTMP varchar(1000)
SET #sTMP = ''
-- Your CTE....
SELECT #sTMP = #sTMP + AR_SALE + ',' FROM CTE2 AS CTE2
Left OUTER JOIN CTE1 AS CTE1
ON CTE1.SAP_SALE = CTE2.AR_SALE
WHERE CTE1.SAP_SALE IS NULL
ORDER BY CTE2.AR_SALE
PRINT #sTMP
WITH CTE1 (SAP_SALE)
AS
(
select distinct convert(BIGINT,convert(varchar(15),WERKS)+(select RIGHT(convert(Varchar(20),BONNR),7)))
as Branch_tx_no from [PDP].[pdp].[S120] WITH (NOLOCK)
where SPTAG >= CAST(CONVERT(VARCHAR(10), GETDATE() -1, 101) AS DATETIME) AND
SPTAG < CAST(CONVERT(VARCHAR(10), GETDATE(), 101) AS DATETIME)
),
CTE2 (AR_SALE)
AS
(
select convert(varchar(15),branch_no)+convert(varchar(15),sale_tx_no)
from [ARDB01].[PP_BODATA].[DBO].[sales_tx_hdr] WITH (NOLOCK)
WHERE sale_date >= CAST(CONVERT(VARCHAR(10), GETDATE() -1, 101) AS DATETIME) AND
sale_date < CAST(CONVERT(VARCHAR(10), GETDATE(), 101) AS DATETIME)
and sale_type in ('C','L')
)
SELECT AR_SALE, row_number() over (order by AR_SALE) as r
into #temp -- added this row right here
FROM CTE2 AS CTE2
Left OUTER JOIN CTE1 AS CTE1
ON CTE1.SAP_SALE = CTE2.AR_SALE
WHERE CTE1.SAP_SALE IS NULL
ORDER BY CTE2.AR_SALE
then...
declare #x varchar(100)
declare #i int
set #i = 1
while (#i <= (select max(r) from #temp)) begin
select #x=AR_SALE from #temp where r=#i
print #x
set #i=#i+1
end

Pivot In Values with dates?

At the end of my sql, I am using the following code. Is there any way of replacing the fixed strings [2011/07/14], [2011/07/16], etc, to GetDate() value?
PIVOT
(
count([AppointmentsBooked])
FOR [date] IN ([2011/07/14], [2011/07/16], [2011/07/17],[2011/07/18],[2011/07/21])
) as pivottable
Can you try to use BETWEEN and DATEADD in following manner:
DECLARE #dates TABLE(value DateTime)
INSERT INTO #dates VALUES
(GETDATE()),
('2011/07/9'),
('2011/07/17'),
('2011/07/18'),
('2011/07/21')
SELECT value FROM #dates
WHERE value BETWEEN GETDATE() AND DATEADD(day, 5, GETDATE())
You can create a string of all dates which is comma seperated with '[' and ']' before and after each date. assign this string to a string variable (#dates) and use the string spit method to split all dates inside the pivot query.
this question was posted about a year ago. i don't care. i have some code that might be exactly what the OP wanted.... i'm sure he'll never come back and chose an answer but still.... all i want to do is count the records by month with a pivot for a few tables and ultimately compare the number of records for each month for each table. however... in this code there is only one table (rt_taco_15m) but that doesn't matter. i just haven't written the rest to completely fit my needs. but i think it fits the needs of the OP or at least gets him on a good start.... if he truly has been waiting a year on this problem. lol.
if object_id('tempdb..#temp') is not null drop table #temp
if object_id('tempdb..#temp2') is not null drop table #temp2
if object_id('tempdb..#temp3') is not null drop table #temp3
declare #start_date as datetime
set #start_date = cast('1-1-2012' as datetime)
declare #end_date as datetime
set #end_date = cast('9-1-2012' as datetime)
;with cte as (
select #start_date as [start],
dateadd(month, 1, #start_date) as [end]
union all
select dateadd(month, 1, [start]) as [start],
dateadd(month, 1, dateadd(month, 1, [start])) as [end]
from cte
where dateadd(month, 1, [start]) <= #end_date
)
(select 'rt_taco_15m' as table_name,
convert(varchar(10), [start], 101) as [start],
convert(varchar(10), [end], 101) as [end],
datename(month, [start]) as month_name,
cast([start] as integer) as orderby,
count(taco.taco_record_id) as [range_count]
into #temp
from cte
left outer join rt_taco_15m as taco
on taco.period >= cte.[start] and
taco.period < cte.[end]
group by cte.[start], cte.[end])
select table_name as table_name,
convert(varchar(10), getdate(), 101) as [start],
convert(varchar(10), getdate(), 101) as [end],
'Total' as month_name,
cast(dateadd(month,2,#end_date) as integer) as orderby,
range_sum as [range_count]
into #temp2
from (select table_name, sum([range_count]) as range_sum
from #temp group by table_name) as summed_up
select *
into #temp3
from (select * from #temp
union all
select * from #temp2) as x
order by orderby
select * from #temp3
declare #cols nvarchar(2000)
select #cols = stuff(
(select '],[' + month_name
from #temp3
order by orderby
for xml path('') )
, 1, 2, '') + ']'
print #cols
if object_id('tempdb..#temp2') is not null drop table #temp2
declare #query varchar(max)
set #query = N'
select table_name, ' + #cols + N'
from (select table_name, month_name, range_count
from #temp3) p
pivot ( sum(range_count) for month_name in ( '+ #cols +' ) ) as pvt'
execute(#query