OPENQUERY in SQL Server shows error - sql

I am using linked server below query but it shows an error. Am I missing any quotes? Can anybody help me?
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 think you want something more like this:
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 >= CAST(''' + #fromdt + ''' as date) AND CAST(''' + #EndDate1 + ''' as date)
';

Related

The column '30' was specified multiple times for 'stat'

i am facing this error on executing query
The column '30' was specified multiple times for 'stat'.
FROM Probale
--WHERE (EntryDate BETWEEN #StartDate AND #Enddate)
ORDER BY EntryDate
DECLARE #cols NVARCHAR(4000)
SELECT #cols = COALESCE(#cols + ',[' + CONVERT(varchar, DATEPART(DAY, EntryDate), 112)
+ ']','[' + CONVERT(varchar,DATEPART(DAY, EntryDate), 112) + ']')
FROM #Dates24
ORDER BY EntryDate
DECLARE #qry NVARCHAR(4000) =
N'SELECT *
FROM (SELECT ItemMasterFile.Descriptionitem,Probale.prdqty,
DATEPART(DAY, Probale.EntryDate)as DDate
FROM Probale Inner Join ItemMasterFile on Probale.Codeitem=ItemMasterFile.Codeitem )prd
PIVOT (Sum(prdqty) FOR DDate IN (' + #cols + ')) AS stat
'
-- Executing the query
EXEC(#qry)```
Your column names should be unique. You can try this for column names.
SELECT #cols = #cols + ',' + QUOTENAME( CONVERT(varchar(2),EntryDate) )
FROM (SELECT DISTINCT DATEPART(DAY, EntryDate) AS EntryDate FROM #Dates24 ) T
ORDER BY EntryDate
SET #cols = STUFF(#cols, 1, 1, '')

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.

Ignore Sunday while generating student attendance report in SQL

This code gives me the attendance report between two dates passed as a parameter.
I will pass dates respective of the month selected from the C# code.
But I want to skip Sundays while generating the attendance report. How can I achieve this?
DECLARE #startdate date = '20180109';
DECLARE #enddate date = '20180112';
DECLARE #cols as varchar(2000);
DECLARE #query as varchar(MAX);
WITH cte (startdate)
AS
(SELECT
#startdate AS startdate
UNION ALL
SELECT
DATEADD(DAY, 1, startdate) AS startdate
FROM cte
WHERE startdate < #enddate
)
select c.startdate
into #tempDates
from cte c
SELECT
#cols = STUFF((SELECT DISTINCT
',' + QUOTENAME(CONVERT(CHAR(10),
startdate, 120))
FROM #tempDates
FOR XML PATH (''), TYPE)
.value('.', 'NVARCHAR(MAX)')
, 1, 1, '')
SET #query = 'SELECT RollNo,FirstName,LastName, ' + #cols + ' from
(
select S.RollNo,U.FirstName,U.LastName,
D.startdate,
convert(CHAR(10), startdate, 120) PivotDate
from #tempDates D,Attendance A, Student S, UserDetails U
where D.startdate = A.Date and A.EnrollmentNo=S.EnrollmentNo and A.EnrollmentNo=U.userID
) x
pivot
(
count(startdate)
for PivotDate in (' + #cols + ')
) p '
EXECUTE (#query)
drop table #tempDates
How about changing #TempDates?
select c.startdate
into #tempDates
from cte c
where datename(weekday, c.startdate) <> 'Sunday';
This assumes that your internationalization settings are set to "English".

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 can I change the ORDER BY clause depending on the parameters that are passed into the stored procedure

I am passing 3 parameters into my stored procedure: #Time, #DeptID, #Value.
#Time is representing: 1=past 24hours, 2=past week, 3=past month, 4=past year
#DeptID is the ID of the various departments
#Value 1=Sort by Low, 2=Sort by High
Here is my current code:
DECLARE #SQL VARCHAR(MAX)
SET #SQL = ('SELECT S.ID, S.[Description], D.Department, S.Value, S.[Date] FROM Suggestions S INNER JOIN Department D ON D.ID = S.DeptID WHERE Approved =1')
IF (#DeptID = 0 AND #Value = 0 AND #Time = 0)
BEGIN
SET #SQL = (#SQL +' ORDER BY [Date] DESC')
END
IF (#Time > 0)
BEGIN
SET #SQL = (CASE WHEN #Time = 1 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -1, GETDATE()) ORDER BY S.[Date] DESC')
WHEN #Time = 2 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -7, GETDATE()) ORDER BY S.[Date] DESC' )
WHEN #Time = 3 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -30, GETDATE()) ORDER BY S.[Date] DESC')
WHEN #Time = 4 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -365, GETDATE()) ORDER BY S.[Date] DESC') END)
END
IF (#DeptID > 0)
BEGIN
SET #SQL = #SQL + ' AND S.DeptID = #DeptID ORDER BY S.[Date] DESC')
END
IF (#Value > 0)
BEGIN
SET #SQL = (CASE WHEN #Value = 1 THEN (#SQL + ' ORDER BY S.Value DESC')
WHEN #Value = 2 THEN (#SQL + ' ORDER BY S.Value ASC')
This is fine when only one parameter is passed in, but when trying to filter by two or more parameters then I run into a problem...
So far I have been getting errors because I am adding 2 'Order By' clause onto the end of my Statement:
ORDER BY S.[Date] DESC ORDER BY S.Value DESC
Can anyone point me in the right direction with this?
Any help at all would be much appriciated
I rewrote your code to not use dynamic SQL:
SELECT S.ID,
S.[Description],
D.Department,
S.Value,
S.[Date]
FROM Suggestions S
INNER JOIN Department D
ON D.ID = S.DeptID
WHERE Approved =1
AND (#Time = 0
OR (#Time = 1 AND [Date] >= DATEADD(DAY, -1, GETDATE()))
OR (#Time = 2 AND [Date] >= DATEADD(DAY, -30, GETDATE()))
OR (#Time = 3 AND [Date] >= DATEADD(DAY, -365, GETDATE()))
)
AND (#DeptID = 0
OR (#DeptID > 0 AND S.DeptID = #DeptID)
)
ORDER BY [Date] DESC,
CASE WHEN #Value = 1 THEN S.Value
ELSE 1 END DESC,
CASE WHEN #Value = 2 THEN S.Value
ELSE 1 END ASC
Updated with dynamic SQL version
Ok, if you want the dynamic SQL solution, then this is one way (but first, did you read this link?):
DECLARE #SQL VARCHAR(MAX), #WHERE VARCHAR(MAX), #ORDER VARCHAR(MAX)
SET #SQL = ('SELECT S.ID, S.[Description], D.Department, S.Value, S.[Date] FROM Suggestions S INNER JOIN Department D ON D.ID = S.DeptID WHERE Approved =1')
SET #WHERE = ' AND ' +
CASE WHEN #Time = 0 THEN '1 = 1'
WHEN #Time = 1 THEN '[Date] >= DATEADD(DAY, -1, GETDATE())'
WHEN #Time = 2 THEN '[Date] >= DATEADD(DAY, -7, GETDATE())'
WHEN #Time = 3 THEN '[Date] >= DATEADD(DAY, -30, GETDATE())'
WHEN #Time = 4 THEN '[Date] >= DATEADD(DAY, -365, GETDATE())' END
SET #WHERE = #WHERE +
CASE WHEN #DeptID > 0 THEN ' AND S.DeptID = #DeptID'
ELSE '' END
SET #ORDER = ' ORDER BY S.[Date] DESC' +
CASE WHEN #Value = 0 THEN ''
WHEN #Value = 1 THEN ', S.Value DESC'
WHEN #Value = 2 THEN ', S.Value ASC' END
SET #SQL = #SQL + #WHERE + #ORDER
PRINT #SQL
Not sure I agree with all of your dynamic SQL but why not just check if the order by clause is already in the SQL String and if it is just add the additional parameter otherwise add the entire clause. You can do this using CharIndex.
I would also suggest only adding the DESC at the very end just before you execute the #SQL
IF (#DeptID = 0 AND #Value = 0 AND #Time = 0)
BEGIN
IF CHARINDEX('ORDER BY',#SQL) = 0
BEGIN
SET #SQL = (#SQL +' ORDER BY [Date] ')
END
ELSE
BEGIN
SET #SQL = (#SQL +',[Date] ')
END
END
SET #SQL = #SQL + ' DESC'
DECLARE #STARTDATE datetime = CASE #Time
WHEN 1 THEN DATEADD(dd, -1, GETDATE())
WHEN 2 THEN DATEADD(ww, -1, GETDATE())
WHEN 3 THEN DATEADD(mm, -1, GETDATE())
WHEN 4 THEN DATEADD(yy, -1, GETDATE())
END
SELECT S.ID,
S.[Description],
D.Department,
S.Value,
S.[Date]
FROM Suggestions S INNER JOIN Department D ON D.ID = S.DeptID
WHERE Approved = 1 AND
(S.DeptID = #DeptId OR #DeptID = 0) AND
[DATEADD] >= #STARTDATE
ORDER BY case #Value when 0 then [Date] else 0 end,
case #Value when 1 then S.Value else S.Value * -1 end
it looks like the criteria for your last two if statements are being met and you're adding your order clause twice.
Try this:
DECLARE #SQL VARCHAR(MAX)
SET #SQL = ('SELECT S.ID, S.[Description], D.Department, S.Value, S.[Date] FROM Suggestions S INNER JOIN Department D ON D.ID = S.DeptID WHERE Approved =1')
IF (#DeptID = 0 AND #Value = 0 AND #Time = 0)
BEGIN
SET #SQL = (#SQL +' ORDER BY [Date] DESC')
END
IF (#Time > 0)
BEGIN
SET #SQL = (CASE WHEN #Time = 1 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -1, GETDATE()) ORDER BY S.[Date] DESC')
WHEN #Time = 2 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -7, GETDATE())' )
WHEN #Time = 3 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -30, GETDATE())')
WHEN #Time = 4 THEN (#SQL + ' AND [Date] >= DATEADD(DAY, -365,GETDATE())') END)
END
IF (#DeptID > 0)
BEGIN
SET #SQL = #SQL + ' AND S.DeptID = #DeptID')
END
IF (#Value > 0)
BEGIN
SET #SQL = (CASE WHEN #Value = 1 THEN (#SQL + ' ORDER BY S.[Date] DESC, S.Value DESC')
WHEN #Value = 2 THEN (#SQL + ' ORDER BY S.[Date] ASC, S.Value ASC')