Dynamic sql syntax with dates - sql

This line in my dynamic sql which feeds some dynamic pivoting, does not seem to take in the correct dates and return the expected results. The query runs and returns no results.
and PA.DATE_RECEIVED BETWEEN
'+ convert(varchar(10), #Startdate, 120) +' AND '+ convert(varchar(10), #Enddate, 120) +'
Check to see what values it is picking up ... Some sql in the stored procedure.
select convert(varchar(10), #Startdate, 120) - 2013-02-02
select convert(varchar(10), #Enddate, 120) - 2013-02-26
Running the query outside in normal sql, it works ? What is the problem.
select COALESCE( PT.[description] , 'Grand Total') AS [Transaction Type],
Sum (AI.PRICE_INC_VAT) AS [AMOUNT (รบ) CREDIT],
P.[DESCRIPTION] AS [PRODUCT TYPE]
From [dbo].[T1] C
join [dbo].[T2] S on S.[Customer_ID]=C.[Customer_ID]
join [dbo].[T3] SO on SO.[SITE_ID]=S.[SITE_ID]
join [dbo].[T4] OI on OI.[ORDER_ID]=SO.[SITE_ORDER_ID]
left join [dbo].[T5] P on P.[PRODUCT_ID]=OI.[PRODUCT_ID]
JOIN [dbo].[T6] AI ON AI.ORDER_ITEM_ID = OI.ORDER_ITEM_ID
JOIN T7 JBAI ON JBAI.ACTION_ITEM_ID = AI.ACTION_ITEM_ID
JOIN T8 JB ON JB.JOB_BATCH_ID = JBAI.JOB_BATCH_ID
JOIN T9 PA on PA.PAYMENT_ID=JB.PAYMENT_ID
LEFT JOIN T10 CU ON JB.CUSTOMER_USER_ID = CU.CUSTOMER_USER_ID
JOIN T11 PT ON PT.PAYMENT_TYPE_ID=PA.PAYMENT_TYPE_ID
LEFT JOIN T12 SU ON SU.SYS_USER_ID=JB.SYS_USER_ID
where P.[PRODUCT_CATEGORY_ID]= (
select PC.[PRODUCT_CATEGORY_ID] from [dbo].[PRODUCT_CATEGORY] PC
where PC.[DESCRIPTION]='BAGS')
and C.COMPANY_ID= '12'
and PA.DATE_RECEIVED BETWEEN '02-FEB-2013' AND '26-FEB-2013'
group by PT.DESCRIPTION, P.DESCRIPTION

You might be missing single quotes around dates, instead of PA.DATE_RECEIVED BETWEEN 2013-02-02 AND 2013-02-26 try to have the string read: PA.DATE_RECEIVED BETWEEN '2013-02-02' AND '2013-02-26'. Here is an example how you can get single quotes in string:
DECLARE #var VARCHAR(1000) =
'and PA.DATE_RECEIVED BETWEEN ''' +
convert(varchar(10), GETDATE(), 120) +
''' AND ''' +
convert(varchar(10), GETDATE(), 120) + ''''
SELECT #var
Single quote in a literal string is denoted by ''.

i think you got a quote problem. note the escaped quote to make a single quote appear in the dynamic query
and PA.DATE_RECEIVED BETWEEN
'''+ convert(varchar(10), #Startdate, 120) +''' AND '''+ convert(varchar(10), #Enddate, 120) +'''

Have you tried this :
and PA.DATE_RECEIVED BETWEEN #Startdate AND #Enddate
You don't have to convert the dates to make the BETWEEN statement work

I think there are a few of issues in your query, (1) forming up your sql string, (2) trying to compare date with varchar values and (3) converting string to date
For example it should be like;
declare #sql nvarchar(max),
#startdate varchar(50) = '20130202', --Using ISO format (yyyymmdd)
#enddate varchar(50) = '20130226' --Using ISO format
select #sql = 'SELECT col1, col2, ... FROM myTable WHERE mydate '+
'between convert(date, ' + #startdate + ') and ' +
'convert(date, ' + #enddate + ')'

Related

How to pass date variable in open query?

I try to pass date variable in open query but it shows error like
"Incorrect syntax near + "
Here is my query:
DECLARE #fromdt DATETIME = '2018-04-07';
DECLARE #EndDate1 DATETIME = '2018-04-07';
Select * from openquery(TIMEV,
'SELECT REPLACE(LTRIM(REPLACE(badgenumber,"0"," "))," ","0") badgenumber,
checktime as dt
from checkinout a
join USERINFO c on c.userid=a.userid
WHERE checktime >= '''''+CONVERT(CHAR(10), #fromdt, 120)+''''' AND ''''' + CONVERT(CHAR(10), #EndDate1, 120) + ''''' ')
I am stuck here .Thanks in advance..
OPENQUERY documentation explicitly says:
OPENQUERY does not accept variables for its arguments.
Therefore, using a trick from this site you should be able to do it like this:
DECLARE #fromdt DATETIME = '2018-04-07';
DECLARE #EndDate1 DATETIME = '2018-04-07';
DECLARE #query nvarchar(max) =
'SELECT * FROM OPENQUERY(TIMEV,
'' SELECT REPLACE(LTRIM(REPLACE(badgenumber,"0"," "))," ","0") badgenumber,
checktime AS dt
FROM checkinout a
JOIN USERINFO c on c.userid=a.userid
WHERE checktime >= ''''' + CONVERT(CHAR(10), #fromdt, 120) + ''''' AND ''''' + CONVERT(CHAR(10), #EndDate1, 120) + ''''' ''
)';
EXEC(#query);
EDIT: there are also two other methods suggested in the link I provided above the code snippet if you wish to try them out.

Keep only Day from Date in column name

i have created a stored procedure by online help to generate a monthly attendance report
USE [Attendace]
GO
/****** Object: StoredProcedure [dbo].[PerDayAttendance] Script Date: 04/11/2018 20:16:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PerDayAttendance]
#STARTDATE DATE,
#ENDDATE DATE
AS BEGIN
WITH DATERANGE AS
(
SELECT DT =DATEADD(DD,0, #STARTDATE)
WHERE DATEADD(DD, 1, #STARTDATE) <= #ENDDATE
UNION ALL
SELECT DATEADD(DD, 1, DT)
FROM DATERANGE
WHERE DATEADD(DD, 1, DT) <= #ENDDATE
) SELECT * INTO cte_DATES
FROM DATERANGE
DECLARE #COLUMN varchar(max)
SELECT #COLUMN=ISNULL(#COLUMN+',','')+ '['+ CAST(CONVERT(DATE , T.DT) AS varchar) + ']' FROM cte_DATES T
DECLARE #Columns2 varchar(max)
SET #Columns2 = SUBSTRING((SELECT DISTINCT ',ISNULL(['+ CAST(CONVERT(DATE , DT)
as varchar )+'],'''') AS ['+ CAST(CONVERT(DATE , DT) as varchar )+']'
FROM cte_DATES GROUP BY dt FOR XML PATH('')),2,8000)
DECLARE #QUERY varchar(MAX)
SET #QUERY = 'SELECT P.EID, ENAME, ' + #Columns2 +', Wdays, Holidays, K.Present, (Wdays-(Holidays + K.Present))as Absent, (cast(((s.Salary/Wdays)*(k.present+Holidays)) as numeric(36,0))) as Salary FROM
(
SELECT A.EID, A.ENAME , B.DT AS DATE, (Case when cast(A.WorkTime as time) >
''00:00:00'' then ''P'' else ''Abs'' end) as worktime FROM TblAttendnce A
RIGHT OUTER JOIN cte_DATES B
ON A.EDATE=B.DT
) X
PIVOT
(
MIN([Worktime])
FOR [DATE] IN (' + #COLUMN + ')
) P
Cross apply (select Wdays, Holidays from dbo.fn_Fn1(''' + CAST(#STARTDATE AS VARCHAR(50)) + ''','''+ CAST(#ENDDATE as Varchar(50))+'''))H
Right Outer Join (select eid, COUNT(present) as present from Attendace.dbo.vwPayroll
where Edate between ''' + CAST(#STARTDATE AS VARCHAR(50)) + '''and'''+ CAST(#ENDDATE as Varchar(50))+'''
group by eid) as K on K.eid=p.EID
Right Outer Join ((select eid, salary from dbo.employeeMast))as s on S.eid=p.eid
WHERE ISNULL(ENAME,'''')<>''''
'
Exec (#QUERY)
DROP TABLE cte_DATES
END
Now the outcome is like this
i need to prepare a crystal report from this procedure, but due to dynamic column header name i am unable to do this.
My Query is how to make column name as 01, 02, 03 instead of 2018-04-01, 2018-04-02, 2018-04-03
i mean i want to rename column name as DD of dd/mm/yyyy
by this way i may able to reflect it in crystal report.
When I am developing a Crystal Report or training a client; I teach them either to rename to the data field in the SQL or stored procedure such date as 3 or Insert a Duplicate Detail line and use the OLD line for Development. Making the NEW Line a Comment Line.

Retrieve data quarterly(each 3 month) and also show last day of quarter

i have a problem, i cant get the sum for quarterly data.
I want my output like this:
#startdate='5/17/2017'
and
#enddate='5/27/2017
output:
AccountNo 06/30/2017
--------------------------
320002101 3453543.67
320003478 103343.56
user chooses two dates, 1st one is #startdate and another #enddate,
Enddate should be determining what quarter to choose of course, if its May then it must show JUNE(6th month) and the last day of quarter.
My query was something like this, but obviously it doesn't work, i tried mixing up things in data functions
SELECT bal.AccountNo,acc.AccountName ,
DATEADD(quarter,DATEDIFF(quarter,0,#enddate),30) [quarter],
SUM(bal.Sum) [quarterlySum]
FROM dbo.Balances AS bal
INNER JOIN dbo.Accounts AS acc
ON acc.AccountNo = bal.AccountNo
WHERE (bal.BalanceDate BETWEEN #startdate AND #enddate)
GROUP BY acc.AccountName,bal.AccountNo
Not really sure below will work, but it's worth to give a go:
declare #startdate date = (select getdate()- 60 )
declare #enddate date = (select getdate() - 30)
select #startdate, #enddate
declare #sql nvarchar(1000)
set #sql =
'SELECT bal.AccountNo,
SUM(bal.Sum) as ''' + replace(convert(nvarchar(10), DATEADD(dd, -1, DATEADD(qq, DATEDIFF(qq, 0, #enddate) +1, 0)), 101), '/', '') +'''
INNER JOIN dbo.Accounts AS acc
ON acc.AccountNo = bal.AccountNo
WHERE (bal.BalanceDate BETWEEN ''' + convert(varchar, #startdate, 101) + ''' AND ''' + convert(varchar, #enddate, 101) +''')
GROUP BY acc.AccountName'
print #sql
exec (#sql)
I do not think so there is another way than doing this dynamically as above.
My question was to get the end of the quarter from currentdate, and also not just end of the quarter, but the end of the month of the end of the quarter from currentdate
And here is the code, i used to retrieve my data
DECLARE #startdate DATE; SET #startdate='5/2/2017';
DECLARE #enddate DATE; SET #enddate='6/13/2017'
DECLARE #datatype VARCHAR; SET #datatype=3;
SELECT bal.AccountNo,acc.AccountName ,
CASE #datatype WHEN 3 THEN SUM(bal.Sumn)END AS [balance]
FROM dbo.Balances AS bal
INNER JOIN dbo.Accounts AS acc
ON acc.AccountNo = bal.AccountNo
WHERE (bal.BalanceDate BETWEEN convert(varchar, #startdate, 101) AND
convert(varchar, #enddate, 101))
GROUP BY acc.AccountName,bal.AccountNo

Getting null value in the Grand Total column in the Pivot Table in sql

I have the query which returning me the number of categories in one cloumn and other column are dynamic column they are giving me the the months between start date & end date and this column are returning me the amount of the categories sold on that month.
I want to add the Grand Total at the end of the row in the query
Here's My Query
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#subtotal AS FLOAT,
#startdate as datetime,
#enddate as datetime
DECLARE #ColumnsRollup AS VARCHAR (MAX)
set #startdate = '1-Mar-2014'
set #enddate = '1-Aug-2014'
;with cte (StartDate, EndDate) as
(
select min(#startdate) StartDate, max(#enddate) EndDate
union all
select dateadd(mm, 1, StartDate), EndDate
from cte
where StartDate < EndDate
)
select StartDate
into #tempDates
from cte
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(CHAR(10), StartDate, 120))
from #tempDates
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') + ',[Total]'
SET #query = 'select ledger_name,
' + #cols + '
from
(
SELECT
CASE WHEN (GROUPING(ledger_name) = 1) THEN ''Grand Total''
ELSE ledger_name END AS ledger_name,
ISNULL(SUM(amount),0) Amount,
CASE WHEN (GROUPING(StartDate) = 1) THEN ''Total''
ELSE convert(CHAR(10), StartDate, 120) END StartDate
FROM #tempDates d
left join Rs_Ledger_Master AS LM on d.StartDate between '''+convert(varchar(10), #startdate, 120)+''' and '''+convert(varchar(10), #enddate, 120)+'''
LEFT OUTER JOIN RS_Payment_Master AS PM ON PM.ledger_code = LM.ledger_code and month(paid_date) = month(StartDate) and year(paid_date) = year(StartDate)
group by
ledger_name,StartDate WITH ROLLUP
) d
pivot
(
SUM(Amount)
for StartDate in (' + #cols + ')
) p
ORDER BY CASE WHEN ledger_name = ''Grand Total'' THEN 1 END'
execute sp_executesql #query;
drop table #tempDates
I think what you can do is, try to use the ROLLUP option in your inner query, which actually returns addtional row for the SUM(Amount), which you can call as Total and add this column to your column list.
Here is the change what I think you need to do
Add total column at the end of your column list
SET #cols= #cols + ',[Total]'
Add the rollup option to your inner query. Note that, the case statement is required to change the text as total for the row.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#subtotal AS FLOAT,
#startdate as datetime,
#enddate as datetime
DECLARE #ColumnsRollup AS VARCHAR (MAX)
set #startdate = '1-Mar-2014'
set #enddate = '1-Aug-2014'
;with cte (StartDate, EndDate) as
(
select min(#startdate) StartDate, max(#enddate) EndDate
union all
select dateadd(mm, 1, StartDate), EndDate
from cte
where StartDate < EndDate
)
select StartDate
into #tempDates
from cte
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(CHAR(10), StartDate, 120))
from #tempDates
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') + ',[Total]'
SET #query = 'select ledger_name,
' + #cols + '
from
(
SELECT
ledger_name,
ISNULL(SUM(amount),0) Amount,
CASE WHEN (GROUPING(StartDate) = 1) THEN ''Total''
ELSE convert(CHAR(10), StartDate, 120) END StartDate
FROM #tempDates d
left join Rs_Ledger_Master AS LM on d.StartDate between '''+convert(varchar(10), #startdate, 120)+''' and '''+convert(varchar(10), #enddate, 120)+'''
LEFT OUTER JOIN RS_Payment_Master AS PM ON PM.ledger_code = LM.ledger_code and month(paid_date) = month(StartDate) and year(paid_date) = year(StartDate)
group by
ledger_name,StartDate WITH ROLLUP
) d
pivot
(
SUM(Amount)
for StartDate in (' + #cols + ')
) p
WHERE ledger_name IS NOT NULL
UNION ALL
select ledger_name,
' + #cols + ' FROM
(SELECT ''Grand Total'' AS ledger_name,
ISNULL(SUM(amount),0) Amount,
CASE WHEN (GROUPING(StartDate) = 1) THEN ''Total''
ELSE convert(CHAR(10), StartDate, 120) END StartDate
FROM #tempDates d
left join Rs_Ledger_Master AS LM on d.StartDate between '''+convert(varchar(10), #startdate, 120)+''' and '''+convert(varchar(10), #enddate, 120)+'''
LEFT OUTER JOIN RS_Payment_Master AS PM ON PM.ledger_code = LM.ledger_code and month(paid_date) = month(StartDate) and year(paid_date) = year(StartDate)
group by StartDate WITH ROLLUP
) d
pivot
(
SUM(Amount)
for StartDate in (' + #cols + ')
) p
'
print #query
execute sp_executesql #query;
drop table #tempDates
You need additional union all to get the last summary row
You can refer the following article for using ROLLUP
http://technet.microsoft.com/en-us/library/ms189305(v=sql.90).aspx

How to flip month and day in a datetime?

How can I flip "2012-12-01 12:33:00.0" to become "2012-01-12 12:33:00.0"? I had tried "select convert(varchar(50), convert(datetime, log_date, 103), 121)" and used both 101 and 103 and still not able to flip it.
The database is MS SQL
DECLARE #date DATETIME
SET DATEFORMAT ydm
SET #date = '2012-12-01 12:33:00.0'
SELECT #date
SET DATEFORMAT ydm will give you the result in your required format.
Other Option
UPDATE Table_Name
SET COLUMN_NAME= convert(varchar(20), convert(Date, #date, 101)) + convert(varchar(30),convert(time, #date))
WHERE
OR
select convert(datetime, convert(varchar(100), #date), 20)
You could just perform some string manipulation (NOTE: Untested code)
UPDATE table
SET date=
LEFT(CONVERT(VARCHAR(50),date,128),4) -- '2012'
+SUBSTRING(CONVERT(VARCHAR(50),date,128),7,3) -- '-01'
+SUBSTRING(CONVERT(VARCHAR(50),date,128),4,3) -- '-12'
+RIGHT(CONVERT(VARCHAR(50),date,128),LEN(CONVERT(VARCHAR(50),date,128))-10) -- ' 12:33:00.0'
You could use the Format function to swap day and month, while keeping the year and hour:
update MyTable
set [date] =
FORMAT([date],'yyyy') + '-' +
FORMAT([date],'dd') + '-' +
FORMAT([date],'MM') + ' ' +
FORMAT([date],'hh:mm:ss')
from MyTable