Return new query if rowcount = 0 - sql

How can I return a new query if my first query didn't return anything? I'm using ssis to execute a stored procedure, if the stored procedure didn't return anything it should pass a new query that will be then saved to a new ole db destination.
Sample Query:
Declare #DepartureDate DATETIME = '4/16/2013',
begin
select PassengerNumber,FromTime,ToTime,Remarks from table a where DepartureDate = #DepartureDate
if (##ROWCOUNT = 0)
begin
Select
'-' [PassengerNumber],
'00:00' [FromTime],
'00:00' [ToTime],
'No Mismatch' [Remarks]
end
End
My problem is that my ole db source returns the blank query instead of the new query provided by the if(##rowcount = 0). So no data is transferred to the ole db source.

how about using UNION?
SELECT PassengerNumber, FromTime, ToTime, Remarks
FROM tableA
WHERE DepartureDate = #DepartureDate
UNION ALL
SELECT '-' [PassengerNumber],
'00:00' [FromTime],
'00:00' [ToTime],
'No Mismatch' [Remarks]
WHERE 0 = (SELECT COUNT(*) FROM tableA WHERE DepartureDate = #DepartureDate)

DECLARE #count INT = -1;
SELECT #count = COUNT(*)FROM TABLE a;
IF (#count > 0)
BEGIN
SELECT PassengerNumber,FromTime,ToTime,Remarks FROM TABLE a;
END
ELSE
SELECT
'-' [PassengerNumber],
'00:00' [FromTime],
'00:00' [ToTime],
'No Mismatch' [Remarks];
END
END

Related

How to avoid not to query tables or views in scalar functions?

I have scalar functions( 4 functions) in my View. It drastically reduces the view's performance. I believe the reason for that is I use SELECT queries in my scalar functions.
EG:
CREATE FUNCTION [dbo].[udf_BJs_GENERAL]
(
#TankSystemId int,
#TimeStamp datetime2(7)
)
RETURNS varchar(10)
AS
BEGIN
DECLARE #leakChk varchar(10);
DECLARE #allowableVariance float;
DECLARE #GallonsPumped int;
DECLARE #DailyOverOrShort float;
DECLARE #TimePeriod datetime2(7);
DECLARE #ReportDate datetime2(7)
SELECT TOP 1 #TimePeriod = Date
FROM [bjs].udv_DailySiraData
where TankSystemId=#TankSystemId ORDER BY Date DESC
SET #ReportDate=#TimePeriod
IF( #TimeStamp <= #TimePeriod)
SET #ReportDate=#TimeStamp
SELECT #GallonsPumped = SUM(GallonsPumped)
FROM [bjs].[udv_DailySiraData]
where TankSystemId=#TankSystemId
and Date <=#ReportDate and Date >= DATEADD(mm, DATEDIFF(mm,0,#ReportDate), 0)
SELECT #DailyOverOrShort = SUM(DailyVar)
FROM [bjs].[udv_DailySiraData]
where TankSystemId=#TankSystemId
and Date <=#ReportDate and Date >= DATEADD(mm, DATEDIFF(mm,0,#ReportDate), 0)
SELECT #allowableVariance= (#GallonsPumped/100) + 130
SET #leakChk='FAIL'
IF (#allowableVariance > ABS(#DailyOverOrShort))
SET #leakChk = 'PASS'
RETURN #leakChk;
How can i avoid such situations? Is there a way to do select queries in my View and pass that result to my scalar function?
Try this:
create function dbo.udf_BJs_GENERAL(
#TankSystemId int,
#TimeStamp datetime2(7)
) returns varchar(10) as
with dates as (
select top 1
ReportDate = case when #TimeStamp <= Date then #TimeStamp else Date
from bjs.udv_DailySiraData
where TankSystemId=#TankSystemId
order by Date desc
),
gallons as (
select
allowableVariance = ( sum(GallonsPumped)/100) + 130,
DailyOverOrShort = sum(DailyVar)
from bjs.udv_DailySiraData data
join dates
on data.Date <= dates.ReportDate
and date.Date >= dateadd(mm, datediffmm, 0, dates.ReportDate), 0)
where TankSystemId = #TankSystemId
)
select
leakChk = cast( case when allowableVariance > ABS(DailyOverOrShort))
then 'PASS' else 'FAIL' end as varchar(10) )
from gallons
your case is special, your have a special input parameter,assue the timestamp parameter is on Day level
This view will return check result of each TankSystemId on every day.
Then join will your query with TankSystemId and Day.
But if the input parameter is more detail. I think it is difficult to convert this function to view
CREATE view [dbo].[uvw_BJs_GENERAL]
AS
BEGIN
/*
SET #ReportDate=#TimePeriod
IF( #TimeStamp <= #TimePeriod)
SET #ReportDate=#TimeStamp
*/
SELECT TankSystemId,b.[Date]
,GallonsPumped = SUM(GallonsPumped),DailyOverOrShort = SUM(DailyVar)
,leakChk=CASE WHEN (SUM(GallonsPumped)/100) + 130)> ABS(SUM(DailyVar)) THEN 'PASS' ELSE 'FAIL' END
FROM [bjs].[udv_DailySiraData] AS a
INNER JOIN (
SELECT CONVERT(DATE,[Date]) AS [Date] FROM [bjs].[udv_DailySiraData] GROUP BY TankSystemId, CONVERT(DATE,[Date])
) b ON a.TankSystemId=b.TankSystemId AND DATEDIFF(d,a.[Date],b.[Date])>=0
-- and Date <=#ReportDate and Date >= DATEADD(mm, DATEDIFF(mm,0,#ReportDate), 0)
GROUP BY TankSystemId,b.[Date]
END

Not able to execute the stored procedure

I have table in which my date column value is saved with time also
like this 2016-06-10 14:56:11.000
Now while executing my SP, I pass one parameter as date like this exec UserReportData '06-10-2016' but it is not showing any records. As it has 4 records in the table.
Why?
UPDATE
ALTER PROCEDURE [dbo].[UserReportData]
#As_ONDATE Datetime
AS
BEGIN
DECLARE #REPORTDATE datetime
DECLARE #OPENING INT
SELECT *
INTO #temptable
FROM
(SELECT DISTINCT
a.CUser_id, b.User_Id,a.U_datetime as REPORTDATE,
b.first_name + ' ' + b.last_name AS USERNAME,
0 OPENING, 0 TOTAL_DOCUMENT, 0 INWARD, 0 FIRST_LEVEL_PROCESSING, 0 DATA_ENTRY
FROM
inward_doc_tracking_trl a, user_mst b
WHERE
a.CUser_id = b.mkey
AND a.U_datetime = CONVERT(varchar(10), #As_ONDATE, 103)) AS x
DECLARE Cur_1 CURSOR FOR
SELECT CUser_id, User_Id
FROM #temptable
OPEN Cur_1
DECLARE #CUser_id INT
DECLARE #User_Id INT
FETCH NEXT FROM Cur_1 INTO #CUser_id, #User_Id
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT #REPORTDATE
FROM inward_doc_tracking_trl
WHERE U_datetime = CONVERT(varchar(10), #As_ONDATE, 103)
UPDATE #temptable
SET REPORTDATE = #REPORTDATE
WHERE CUser_id = #CUser_id
AND User_Id = #User_Id
FETCH NEXT FROM Cur_1 INTO #CUser_id, #User_Id
END
CLOSE Cur_1
DEALLOCATE Cur_1
SELECT *
FROM #temptable
DROP TABLE #temptable
END
You are passing in a date as a string (with implicit time being 00:00) which you are casting to be a date, still with time being 00:00, and trying to match dates with times. There won't be any results as the time doesn't match.
You have to either:
Cast the datetime to a date to match an exact date (not good, requires recalculating every date in the column)
Change the search to look between date + '00:00' to date + '23:59' (or if you are happy, you could just add a day)
Update for your where clause to take the easy option 2:
where a.CUser_id = b.mkey
and a.U_datetime BETWEEN CONVERT(varchar(10), #As_ONDATE, 103)
AND DATEADD(day, 1, CONVERT(varchar(10), #As_ONDATE, 103))

return data even if they are errors

I have a stored procedure, in which return a table containing date,presence,total working hour if present...
Total Working Hour is calculated in a separate function that return a decimal value, But sometimes employees have a mistakes in data, like a duplicate punches or punch (out or in) for twice,
if any of the above scenario exist the function returned an error, and therefore The SP return error...
My request is when any error is occurred, i want to return 0 or -1 or whatever instead of the error, to forces the SP to return data even if they are errors..
The Error generating every time is :
SQL Server Subquery returned more than 1 value.
This is not permitted when the subquery follows =, !=, <, <= , >, >=
So I want in every time when this error occurred, to return a value instead of it,
the SP Code is:
ALTER PROCEDURE [dbo].[SM_GetAttendance]
(
#StartDate date ,
#EndDate date ,
#EmployeeID NVARCHAR(6)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE dte_Cursor CURSOR FOR
WITH T(date)
AS
(
SELECT #StartDate
UNION ALL
SELECT DateAdd(day,1,T.date) FROM T WHERE T.date < #EndDate
)
SELECT date FROM T OPTION (MAXRECURSION 32767);
DECLARE #date NVARCHAR(20);
CREATE TABLE #datetable(date DATETIME,Status NVARCHAR(50),nbOfWorkingHour DECIMAL(36,2))
--SELECT date FROM T
set #date = ''
OPEN dte_Cursor
FETCH NEXT FROM dte_Cursor INTO #date
WHILE ##FETCH_STATUS = 0
BEGIN
insert #datetable
SELECT
cast((select distinct Convert(Nvarchar(12),date,102) from Attendance where date = #date
and employeeid =#EmployeeID ) as nvarchar(30))
date
,CASE WHEN EXISTS (select 1 from Attendance
where employeeid=#EmployeeID and date = #date)
then 'Present'
else 'absent'
end Status
,dbo.GetWorkingHourPerDay(#date,#EmployeeID) as numberOFWorkingHour
FETCH NEXT FROM dte_Cursor INTO #date
END
CLOSE dte_Cursor;
DEALLOCATE dte_Cursor;
end
And The Part of the Function Code that get the error is:
SET #From = (SELECT Time from #Tbl where date = #Date AND (EmployeeID=#employeeID OR ISNULL( #employeeID, '') = '') and funckey = 'EMPIN')
set #to = (CASE WHEN EXISTS(SELECT Times from #Tbl where dates = #Date AND (EmployeeID=#employeeID OR ISNULL( #employeeID, '') = '') and funckey = 'EMPOUT' )
then (SELECT Time from #Tbl where date = #Date AND (EmployeeID=#employeeID OR ISNULL( #employeeID, '') = '') and funckey = 'EMPOUT' )
else (SELECT Top 1 Time from #Tbl where date = dateadd(day,1,#Date) AND (EmployeeID=#employeeID OR ISNULL( #employeeID, '') = '') and funckey = 'EMPOUT')
end)
return ROUND(CAST(DATEDIFF(#From,#to) AS decimal)/ 60,2)
the following piece of code that get the error :
(CASE WHEN EXISTS(SELECT Times from #Tbl where dates = #Date AND (EmployeeID=#employeeID OR ISNULL( #employeeID, '') = '') and funckey = 'EMPOUT' )
IN this example the employee have two out punches like the below :
EMPID Date Time Status
123 2015-10-22 06:54:42 AM OUT
123 2015-10-22 04:35:02 PM OUT
So how to how to handle this state?
You can just change
(CASE WHEN EXISTS(SELECT Times from #Tbl where dates = #Date AND (EmployeeID=#employeeID OR ISNULL( #employeeID, '') = '') and funckey = 'EMPOUT' )
To this
(CASE WHEN EXISTS(SELECT top 1 Times from #Tbl where dates = #Date AND (EmployeeID=#employeeID OR ISNULL( #employeeID, '') = '') and funckey = 'EMPOUT' )

Update data based on other column

I have a table and want to update a column based on other column of same table. Please look at below image for table design and table data.
In this tbl I want to update JoinDate as below steps.
1) if ModifiedDatetime is not null then ModifiedDatetime else CreatedDate.
2) Now if NextLevel is Hour then want to add hour of above date which we have in setp 1
3) Now if NextLevel is Day then want to add Day of above date which we have in setp 1
4) Now if NextLevel is Min then want to add Min of above date which we have in setp 1
5) Finally after completing all above process the date which I will get , I want to use to that data to update joindate.
I did this usig below cursor but I wnat to do this using sql update query.
DECLARE #EmpID INT
Declare #DtTm datetime
DECLARE #NextLevl INT
Declare #JoinDtTm datetime
DECLARE CurProg CURSOR FOR
select EmpID from tblEmp
OPEN CurProg
FETCH NEXT
FROM CurProg INTO #EmpID
WHILE ##FETCH_STATUS = 0
BEGIN
select #DtTm = case when ModifiedTime is null then CreatedDate else ModifiedTime end, #NextLevl = NextLevel from tblEmp where EmpID = #EmpID
if (#NextLevl = 'Min')
BEGIN
set #JoinDtTm = DATEADD(MI,1,#DtTm)
END
ELSE IF (#NextLevl= 'Hour')
BEGIN
set #JoinDtTm = DATEADD(HH,1,#DtTm)
END
ELSE
BEGIN
set #JoinDtTm = DATEADD(D,1,#DtTm)
END
--update tblEmp set JoinDtTm = #JoinDtTm where EMPId= #EMPId
FETCH NEXT
FROM CurProg INTO #EmpID
END
CLOSE CurProg
DEALLOCATE CurProg
Thanks,
Hitesh
Try this:
UPDATE TableName
SET JoinDate = CASE WHEN NextLevel = 'Hour' THEN DATEADD(HH,1,ISNULL(ModifiedDate,CreatedDate))
WHEN NextLevel = 'Day' THEN DATEADD(DD,1,ISNULL(ModifiedDate,CreatedDate))
WHEN NextLevel = 'Min' THEN DATEADD(MI,1,ISNULL(ModifiedDate,CreatedDate))
END
To do this without a cursor in an update statement then this should work
UPDATE TBL_EMP
SET JOINDATE =
(CASE WHEN MODIFIEDTIME IS NOT NULL
THEN (CASE WHEN NEXTLEVEL ='Hour' THEN dateadd(hh,1,modifiedtime)
ELSE (CASE WHEN NEXTLEVEL = 'Day' THEN dateadd(dd,1,MODIFIEDTIME)
ELSE(CASE WHEN NEXTLEVEL = 'Min' THEN dateadd(n,1,MODIFIEDTIME) ELSE MODIFIEDTIME END) END) END)
ELSE(CASE WHEN NEXTLEVEL ='Hour' THEN dateadd(hh,1,CREATEDDATE)
ELSE(CASE WHEN NEXTLEVEL = 'Day' THEN dateadd(dd,1,CREATEDDATE)
ELSE(CASE WHEN NEXTLEVEL = 'Min' THEN dateadd(n,1,CREATEDDATE) ELSE CREATEDDATE END) END) END) END)
FROM TBL_EMP
Drop your column joindate, it is redundant. Since joindate always rely on other columns in the same row, all you need is a computed column like this, otherwise you are stuck on constantly maintaining the values in joindate:
ALTER TABLE YourTable
ADD cJoindate as
CASE NextLevel
WHEN 'day' THEN DATEADD(D, 1, COALESCE(ModifiedDate,CreatedDate))
WHEN 'min' THEN DATEADD(MI, 1, COALESCE(ModifiedDate,CreatedDate))
WHEN 'hour' THEN DATEADD(HH, 1, COALESCE(ModifiedDate,CreatedDate))
END

How to use IF statement in SQL Server 2005?

This is the scenario I would like to have in my INSERT in a stored procedure.
Tables:
tblRate
RateID (pk)
Rate money
Days int
isDailyRate bit
tblBooking
Totals money
In my vb app this is the statement. How would I translate this into T-SQL?
if !isDaily = True then
!Totals = (!Days * !Rate)
else
!Totals = !Rate
end if
This is my stored procedure:
Create PROCEDURE [dbo].[sp_tblBooking_Add]
(
#RateID bigint,
#Rate money,
#Days int,
#CheckOUT datetime
)
AS
BEGIN
--Below is the logic I want. I can't get the right syntax
--Declare #myTotals as money
--Declare #myCheckOut as DateTime
--if (Select isDailyRate FROM tblRates WHERE (RateID = #RateID)) = True THEN
-- set myTotals = (#Rate * #Days)
-- set #CheckOUT = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) + #Days, '12:00')
--Else
-- set myTotals = #Rate
-- set #CheckOUT = GETDATE()
--End if
INSERT INTO tblBooking(Totals, CheckOUT)
VALUES(#myTotals, #myCheckOut);
END
Use the CASE expression:
INSERT INTO tblBooking (Totals, CheckOUT)
SELECT
CASE
WHEN idDailyRate = 1 THEN #Rate * #Days
ELSE #rate
END,
CASE
WHEN idDailyRate = 1 THEN DATEADD(DAY,
DATEDIFF(DAY, 0, GETDATE()) + #Days,
'12:00')
ELSE GETDATE()
END
FROM tblRates
WHERE RateID = #RateID;
Or, if they are scalar values, then you can select them into a variables and insert them instead of INSERT ... INTO ... SELECT.
Update 1
Like this:
Declare #myTotals as money;
Declare #myCheckOut as DateTime;
SELECT
#myTotals = CASE
WHEN idDailyRate = 1 THEN #Rate * #Days
ELSE #rate
END,
#myCheckOut = CASE
WHEN idDailyRate = 1 THEN DATEADD(DAY,
DATEDIFF(DAY, 0, GETDATE()) + #Days,
'12:00')
ELSE GETDATE()
END
FROM tblRates
WHERE RateID = #RateID;
INSERT INTO tblBooking (Totals, CheckOUT) VALUES(#myTotals, #myCheckOut );
But this will give you an error, if there is more than value returned from this table tblRates into those variables.