Check result of transaction before updating table - sql

I have the following stored procedure:
CREATE PROCEDURE [dbo].[vRpt_VolunteerPaymentsAll]
#startdate DATETIME = NULL ,
#enddate DATETIME = NULL ,
#user NVARCHAR(50)
AS /* This procedure generates Team Events that have been audtied */
DECLARE #sd DATETIME
DECLARE #ed DATETIME
/* Ensure that the start and end dates covert whole days */
SET #sd = CONVERT(VARCHAR(10), #startdate, 120) + ' 00:00:00'
SET #ed = CONVERT(VARCHAR(10), #enddate, 120) + ' 23:59:59'
DECLARE #id INT
INSERT INTO vVolunteerPaymentEvents
( StartDate ,
EndDate ,
Verifier ,
DatePaid ,
RecordsPaid ,
UnDone ,
Comments ,
Flags
)
VALUES ( #startdate ,
#enddate ,
/*Get the users initials*/
( SELECT dbo.vUsers.Initials
FROM dbo.vUsers
WHERE dbo.vUsers.UserID = #user
) ,
GETDATE() ,
/* Count how many records are going ot be affected*/
( SELECT COUNT(*)
FROM dbo.vVolunteerPayments
WHERE dbo.vVolunteerPayments.PaymentEventID = 0
AND ( dbo.vVolunteerPayments.DateCreated BETWEEN #sd
AND
#ed )
) ,
0 ,
'' ,
0
)
/*Set the id of the payment event id for the volunteer payments*/
SET #id = SCOPE_IDENTITY() ;
--get the totals for the payment based on the
--#id value just inserted above
UPDATE dbo.vVolunteerPayments
SET dbo.vVolunteerPayments.PaymentEventID = #id ,
dbo.vVolunteerPayments.DatePaid = GETDATE()
WHERE dbo.vVolunteerPayments.PaymentEventID = 0
AND dbo.vVolunteerPayments.DateCreated BETWEEN #sd
AND #ed
SELECT * FROM
(SELECT VOLSACCT.volunteerid ,
ISNULL(VOLS.Forename, '') + ' ' + ISNULL(VOLS.Surname, '') AS Name ,
VOLSACCT.SortCode ,
VOLSACCT.AccountName ,
VOLSACCT.AccountNumber ,
SUM(CASE [Type]
WHEN 1001
THEN CASE WHEN PMTS.DateCreated BETWEEN #sd AND #ed
--AND PMTS.PaymentEventID = 0
--AND PMTS.VolunteerId = #volunteerid
THEN Amount
END
ELSE 0
END) AS Reimbursements ,
SUM(CASE [Type]
WHEN 1002
THEN CASE WHEN PMTS.DateCreated BETWEEN #sd AND #ed
--AND PMTS.PaymentEventID = 0
--AND PMTS.VolunteerId = #volunteerid
THEN Amount
END
ELSE 0
END) AS MobilePhoneCharges ,
SUM(CASE [Type]
WHEN 1003
THEN CASE WHEN PMTS.DateCreated BETWEEN #sd AND #ed
--AND PMTS.PaymentEventID = 0
--AND PMTS.VolunteerId = #volunteerid
THEN Amount
END
ELSE 0
END) AS GPContributions ,
SUM(CASE [Type]
WHEN 12
THEN CASE WHEN PMTS.DateCreated BETWEEN #sd AND #ed
--AND PMTS.PaymentEventID = 0
--AND PMTS.VolunteerId = #volunteerid
THEN Amount
END
ELSE 0
END) AS GPExpenses ,
SUM(CASE [Type]
WHEN 137
THEN CASE WHEN PMTS.DateCreated BETWEEN #sd AND #ed
--PaymentEventID = 0
--AND PMTS.VolunteerId = #volunteerid
THEN Amount
END
ELSE 0
END) AS Expenses ,
SUM(CASE WHEN PMTS.DateCreated BETWEEN #sd AND #ed
--AND PMTS.PaymentEventID = 0
--AND PMTS.VolunteerId = #volunteerid
THEN Mileage
ELSE 0
END) AS TotalMileageWeek ,
VOLSACCT.BACS,
PMTS.ChargeRate
FROM dbo.vVolunteerPayments PMTS
INNER JOIN dbo.vVolunteerAccounts VOLSACCT ON PMTS.VolunteerId = VOLSACCT.VolunteerID
INNER JOIN dbo.vVolunteers VOLS ON PMTS.VolunteerId = VOLS.VolunteerID
WHERE PMTS.PaymentEventID = #id
GROUP BY VOLSACCT.volunteerid ,
VOLSACCT.AccountName ,
VOLSACCT.AccountNumber ,
VOLSACCT.BACS ,
VOLSACCT.SortCode ,
VOLS.Forename ,
VOLS.Surname,
PMTS.ChargeRate) AS A
WHERE
GPContributions >0
OR GPExpenses > 0
OR MobilePhoneCharges > 0
OR Expenses > 0
OR Reimbursements > 0
OR Expenses > 0
OR TotalMileageWeek >0
ORDER BY Name
It basically inserts a summary record of affected transactions into one table (volunteerpaymentevent) , updates existing records of another table (volunteerpayments(datepaid and payment event id)) and then returns record sets of sumary values within a join
However I have found that if the join fails or there are no joins at all (and consequently nothing outputs) then the update part of the procedure still updates the records
Is there a way of checking the result of the inner join before updating the records in the volunteerpayments table
Cheers

You need to put your code inside a transaction:
ALTER PROCEDURE [dbo].[vRpt_VolunteerPaymentsAll]
#startdate DATETIME = NULL ,
#enddate DATETIME = NULL ,
#user NVARCHAR(50)
AS
begin transaction
your procedure code
commit transaction
See MSDN for more on transactions.

Related

Combine multiple queries in 1 return row

I have a query which should return 1 row for each DetectorID. What we currently have is the following:
DECLARE #StartDate datetime SET #StartDate = '2017-12-01 00:00'
DECLARE #EndDate datetime select #EndDate ='2018-01-01 00:00'
DECLARE #Limit1 real SET #Limit1 = 200; DECLARE #AssenLimit1 real SET #AssenLimit1 = 0;
DECLARE #Limit2 real SET #Limit2 = 300; DECLARE #AssenLimit2 real SET #AssenLimit2 = 0;
DECLARE #Limit3 real SET #Limit3 = 350; DECLARE #AssenLimit3 real SET #AssenLimit3 = 0;
DECLARE #Limit4 real SET #Limit4 = 400; DECLARE #AssenLimit4 real SET #AssenLimit4 = 0;
DECLARE #Limit5 real set #Limit5 = 500; DECLARE #AssenLimit5 real SET #AssenLimit5 = 0;
SELECT DetectorID, AVG(ValidWIM) AS 'PI_mean_WIM',
COUNT(ValidWIM) AS 'PI_mean_WIM2',
COUNT(CASE
WHEN ValidWIM > 0.5 THEN ValidWIM ELSE NULL END)
AS 'PI_mean_WIM3'
,AVG((ValidWDD_Left+ValidWDD_Right)/2) AS 'PI_mean_WDD'
,COUNT(ValidWDD_Left) AS 'PI_mean_WDD2'
,COUNT (CASE
WHEN (ValidWDD_Left>0.5 AND ValidWDD_Right>0.5) THEN ValidWDD_Left ELSE NULL END)
AS PI_mean_WDD3
,COUNT(CASE
WHEN AxleLoad IS NOT NULL Then TrainPassageInformationID ELSE NULL END)
AS 'nWheels'
, COUNT(CASE
WHEN (PeakForceLeft > #Limit1 OR PeakForceRight>#Limit1) THEN TrainPassageInformationID ELSE NULL END)
AS 'n>200'
, COUNT(CASE
WHEN (PeakForceLeft > #Limit2 OR PeakForceRight>#Limit2) THEN TrainPassageInformationID ELSE NULL END)
AS 'n>300'
, COUNT(CASE
WHEN (PeakForceLeft > #Limit3 OR PeakForceRight>#Limit3) THEN TrainPassageInformationID ELSE NULL END)
AS 'n>350'
, COUNT(CASE
WHEN (PeakForceLeft > #Limit4 OR PeakForceRight>#Limit4) THEN TrainPassageInformationID ELSE NULL END)
AS 'n>400'
, COUNT(CASE
WHEN (PeakForceLeft > #Limit5 OR PeakForceRight>#Limit5) THEN TrainPassageInformationID ELSE NULL END)
AS 'n>500'
From WheelDamage
where (TimeOfAxle > #StartDate AND TimeOfAxle < #EndDate) and DetectorID in (11,12)
GROUP BY DetectorID
order by DetectorID asc
SELECT DetectorID,
AVG(PeakForceLeft) AS 'NoiseLeft' FROM WheelDamage as t
where PeakForceLeft in (
select top 10 percent PeakForceLeft
from wheeldamage as tt
where tt.WheelDamageID = t.WheelDamageID AND tt.PeakForceLeft <> 0 AND tt.PeakForceLeft IS NOT NULL AND (t.TimeOfAxle > #StartDate AND t.TimeOfAxle < #EndDate)
order by tt.PeakForceLeft asc)
Group By DetectorID
order by DetectorID asc
SELECT DetectorID,
AVG(PeakForceRight) AS 'NoiseRight' FROM WheelDamage as t
where PeakForceLeft in (
select top 10 percent PeakForceRight
from wheeldamage as tt
where tt.WheelDamageID = t.WheelDamageID AND tt.PeakForceRight <> 0 AND tt.PeakForceLeft IS NOT NULL AND (t.TimeOfAxle > #StartDate AND t.TimeOfAxle < #EndDate)
order by tt.PeakForceLeft asc)
Group By DetectorID
order by DetectorID asc
SELECT DetectorId, COUNT (DateTime) AS 'Tags1'
FROM [TagPassage]
WHERE Valid = 1 AND (DateTime > #StartDate AND DateTime < #EndDate)
GROUP by DetectorID
Order by DetectorID asc
SELECT DetectorID, COUNT(CASE
WHEN (TotalWeight=0 OR TotalWeight IS NULL) AND (HasTrainStandStill<>1 OR HasTrainStandStill IS NULL) THEN (TrainPassageInformationID) ELSE NULL END) AS 'notAnalyzed'
, SUM (TotalWeight) AS 'TotalWeight'
FROM TrainPassageInformation
WHERE (Datetime > #StartDate AND Datetime < #EndDate)
Group By DetectorID
order by DetectorID asc
This is returing 5 new rows which I understand. This is because i have 5 select statements. However, I need to know how i can put the bottom 4 select statements in the top one so that it will only return 1 row.
I have tried with Select(Select X xxx). But that gave the error that it is returning more then 1 rows.
The image above is showing the current result. I want the bottom 4 tables to be columns in the first table.
can you just join/left join all the scripts together as table and link by DetectorID, then u can select the columns from the 4 scripts at the bottom to the right.

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' )

After Insert Trigger and multiple rows

These are my tables
CREATE TABLE Courses
(
Course_ID INT IDENTITY (100 , 10) NOT NULL ,
CONSTRAINT PK_Courses PRIMARY KEY (Course_ID)
Catalog_Course_ID NVARCHAR(10) NOT NULL,
CONSTRAINT FK_Catalog_Course_ID FOREIGN KEY (Course_Number_ID) REFERENCES Course_Catalog (Course_Number_ID)
Schedule_ID INT NOT NULL ,
CONSTRAINT FK_Schedule_ID FOREIGN KEY (Schedule_ID) REFERENCES Classs_Schedule(Schedule_ID)
S_Date DATE NOT NULL ,
E_Date DATE NOT NULL ,
)
CREATE TABLE Course_Management
(
Number INT IDENTITNY (1,1) PRIMARY KEY '
Course_ID INT NOT NULL ,
CONSTRAINT FK_Course_ID FOREIGN KEY (Course_ID) REFERENCES Courses (Course_ID)
Course_Date_Meeting DATE NOT NULL,
Duration INT NOT NULL ,
)
Now what I want to do is to insert data to Courses table, the Course_Management will hold all the meeting that happened or will happen in the course.
Schedule_ID - which days the course have a meeting and also how many hours will be the meating.
Catalog_Course_ID can find the total hours of the course
So if I insert one course with Course_Number_ID (from catalog course table), Schedule_ID and S.Date (strat date) the trigger will find how many meetings we should do (by finding the course duration and divide it by meeting duration ) after finding the all meetings, E.Date (end date) will be update as the last meeting that inserted.
I wrote this trigger
CREATE TRIGGER CouseMetting
ON [dbo].[Courses] AFTER INSERT
AS
BEGIN
DECLARE #Course_ID INT --Last Course ID insert
SET #Course_ID = (Select ##IDENTITY)
DECLARE #CCID INT -- Course Catlog ID reference to CourseID last insert
SET #CCID = (SELECT [Course_Number_ID]
FROM [dbo].[Courses]
WHERE [Course_ID] = #Course_ID)
DECLARE #NUM INT -- Duration of the course in hours reference Course Catlog ID
SET #NUM = (select [Duration]
from [dbo].[Course_Catalog] where [Number_ID] = #CCID)
DECLARE #MET INT -- Numbers of meeting
DECLARE #DUR INT -- Duration of 1 meeting
DECLARE #DATE DATE -- Start date of the CourseID
SET #DATE = (SELECT [S_Date]
FROM [dbo].[Courses]
WHERE [Course_ID] = #Course_ID)
DECLARE #Holiday varchar (24) -- Holiday in Israel
DECLARE #DAY_NAME NVARCHAR(10) -- English day name
DECLARE #Schedule_ID INT
SET #Schedule_ID = (SELECT [Schedule_ID]
FROM [dbo].[Courses]
WHERE [Course_ID] = #Course_ID)
SET #DUR = (SELECT [Meeting_Dur]
FROM [dbo].[Classs_Schedule] WHERE [Schedule_ID] = #Schedule_ID)
SET #MET = #NUM/#dur
While #MET > 0
Begin
SET #Holiday = (SELECT [HolidayISR] FROM [dbo].[FullDates] WHERE [Date] = #DATE)
IF #Holiday IS NULL
BEGIN
INSERT INTO [dbo].[Course_Management] ([Course_ID] , [Course_Date_Meeting] ,[Duration] )
VALUES (#Course_ID , #DATE , #DUR )
SET #met = #met - 1
END
SET #DAY_NAME = (SELECT [DayName] FROM [dbo].[FullDates] WHERE [Date] = #DATE)
IF #Schedule_ID = 1
BEGIN
IF #DAY_NAME LIKE 'Sunday'
BEGIN
SET #DATE= DATEADD(DD , 2 , #DATE)
END
ELSE SET #DATE= DATEADD(DD , 5 , #DATE)
END
IF #Schedule_ID = 2
BEGIN
IF #DAY_NAME LIKE 'Sunday'
BEGIN
SET #DATE= DATEADD(DD , 3 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 4 , #DATE)
END
IF #Schedule_ID = 3
BEGIN
IF #DAY_NAME LIKE 'Sunday'
BEGIN
SET #DATE= DATEADD(DD , 4 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 3 , #DATE)
END
IF #Schedule_ID = 4
BEGIN
IF #DAY_NAME LIKE 'Sunday'
BEGIN
SET #DATE= DATEADD(DD , 2 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 5 , #DATE)
END
IF #Schedule_ID = 5
BEGIN
IF #DAY_NAME LIKE 'Sunday'
BEGIN
SET #DATE= DATEADD(DD , 3 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 4 , #DATE)
END
IF #Schedule_ID = 6
BEGIN
IF #DAY_NAME LIKE 'Sunday'
BEGIN
SET #DATE= DATEADD(DD , 4 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 3 , #DATE)
END
IF #Schedule_ID = 7
BEGIN
IF #DAY_NAME LIKE 'Monday'
BEGIN
SET #DATE= DATEADD(DD , 2 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 5 , #DATE)
END
IF #Schedule_ID = 8
BEGIN
IF #DAY_NAME LIKE 'Monday'
BEGIN
SET #DATE= DATEADD(DD , 3 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 4 , #DATE)
END
IF #Schedule_ID = 9
BEGIN
IF #DAY_NAME LIKE 'Monday'
BEGIN
SET #DATE= DATEADD(DD , 2 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 5 , #DATE)
END
IF #Schedule_ID = 10
BEGIN
IF #DAY_NAME LIKE 'Monday'
BEGIN
SET #DATE= DATEADD(DD , 3 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 4 , #DATE)
END
IF #Schedule_ID = 11
BEGIN
IF #DAY_NAME LIKE 'Tuesday'
BEGIN
SET #DATE= DATEADD(DD , 2 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 5 , #DATE)
END
IF #Schedule_ID = 12
BEGIN
IF #DAY_NAME LIKE 'Tuesday'
BEGIN
SET #DATE= DATEADD(DD , 2 , #DATE)
END
ELSE SET #DATE = DATEADD(DD , 5 , #DATE)
END
END
UPDATE [dbo].[Courses]
SET [E_Date] = (SELECT TOP 1 [Course_Date_Meeting]
FROM [dbo].[Course_Management]
WHERE Course_ID = #Course_ID
ORDER BY [Course_Date_Meeting] DESC )
END
The Fulldates table is table the hold all the dates and holidays so if the meeting date is some holiday that trigger will now insert it and will continue to the next meeting
Now if I insert one course with Course_Number_ID (from catalog courses table) and a Schedule_ID and S.Date, every thing works fine.
When I try to insert multiple rows for the course table it works but for the Course_Management only the last row that has been inserted.
I got 5K rows table with Course_Number_ID , Schedule_ID , S.Date and I want to insert it.
I also tried to enter row by row with where clause and it's working.
So the only problem it with multiple rows.
Anyone know where is the problem?

remove duplicates in sql query

I've been working on a query that should :
business logic - show all members who attended the gym(selected from dropdown) within a specified date range.
Problem encountered -I realised that results shows duplicates of which mustn't , may you please assist.
Below is the query I used.
Declare #StartDate datetime = '29 May 2014'
Declare #EndDate datetime = '29 May 2014'
DEclare #SiteID INT =14
Declare #StartTime datetime = '05:00 AM'
Declare #EndTime datetime = '10:00 PM'
Declare #Start datetime = cast (#StartDate + ' '+ #StartTime as datetime)
Declare #End datetime = cast(#EndDate + ' ' + #EndTime as datetime )
SELECT isnull(atc.totalaccepted,0) TotalAcceptedVisits,ISNULL(att.TotalOverrideVisits, 0) AS TotalOverrides, isnull(att1.TotalOverrideDenieds,0) as TotalDenies, ast.Name as VisitiedSite, c.FirstName + ' ' + c.LastName as Name, md.MemRefNo
FROM Contacts c
inner JOIN Attendance a on a.ContactGUID = c.GUID
inner JOIN MemberDetail md on md.ContactGUID = c.GUID
inner JOIN Sites ast on a.SiteID = ast.ID
OUTER APPLY
(
SELECT a1.contactguid,COUNT(*) totalaccepted
FROM Attendance a1
WHERE a1.contactguid = c.guid
AND (a1.IsSwipeSuccessful = 1)
AND a1.accessoverridereasonid IS NULL
AND a1.AttendDate BETWEEN #Start AND #End
group by a1.contactguid
)atc
outer APPLY
(
SELECT a2.contactguid, COUNT(*) TotalOverrideVisits
FROM Attendance a2
WHERE a2.contactguid = c.guid
And (a.IsSwipeSuccessful = 1)
AND a2.accessoverridereasonid IS NOT NULL
AND a2.AttendDate BETWEEN #Start AND #End
and (a2.SiteID = #SiteID OR #SiteID = 0)
group by a2.contactguid
) att
OUTER APPLY
(
SELECT a3.contactguid,COUNT(*) TotalOverrideDenieds
FROM Attendance a3
WHERE a3.contactguid = c.guid
AND a3.IsSwipeSuccessful = 0
AND a3.accessoverridereasonid IS NULL
AND a3.AttendDate BETWEEN #Start AND #end
group by a3.contactguid
) att1
where (a.SiteID = #SiteID OR #SiteID = 0)
and a.AttendDate BETWEEN #Start AND #End
order by md.MemRefNo
Results: as you can see below there are members repeating themselves, I only need to see one row of each member with the number of total visits if any, overrides if any and denied visits if any.
TotalAcceptedVisits TotalOverrides TotalDenies VisitiedSite Name memRefNo
1 0 0 Groblersdal Jean T G0030
1 1 1 Groblersdal Koky Bakkes G0032
1 0 1 Groblersdal Koky Bakkes G0032
1 1 1 Groblersdal Koky Bakkes G0032
1 0 0 Groblersdal Naomi Fisher G0035
1 0 0 Groblersdal Arthur Bart G0089
1 0 0 Groblersdal Tulinda Swi G0034
1 1 0 Groblersdal Devon Mooi G0008
1 1 0 Groblersdal Devon Mooi G0008
I think you will need something like this:
Declare #StartDate datetime = '29 May 2014'
Declare #EndDate datetime = '29 May 2014'
DEclare #SiteID INT =14
Declare #StartTime datetime = '05:00 AM'
Declare #EndTime datetime = '10:00 PM'
Declare #Start datetime = cast (#StartDate + ' '+ #StartTime as datetime)
Declare #End datetime = cast(#EndDate + ' ' + #EndTime as datetime )
SELECT CASE WHEN TotalAcceptedVisits > 0 THEN 1 ELSE 0 END AS TotalAcceptedVisits,
CASE WHEN TotalOverrides > 0 THEN 1 ELSE 0 END AS TotalOverrides,
CASE WHEN TotalDenies > 0 THEN 1 ELSE 0 END AS TotalDenies,
VisitiedSite, Name, MemRefNo
FROM
(SELECT SUM(isnull(atc.totalaccepted,0)) TotalAcceptedVisits, SUM(ISNULL(att.TotalOverrideVisits, 0)) AS TotalOverrides, SUM(isnull(att1.TotalOverrideDenieds,0)) as TotalDenies, ast.Name as VisitiedSite, c.FirstName + ' ' + c.LastName as Name, md.MemRefNo
FROM Contacts c
inner JOIN Attendance a on a.ContactGUID = c.GUID
inner JOIN MemberDetail md on md.ContactGUID = c.GUID
inner JOIN Sites ast on a.SiteID = ast.ID
OUTER APPLY
(
SELECT a1.contactguid,COUNT(*) totalaccepted
FROM Attendance a1
WHERE a1.contactguid = c.guid
AND (a1.IsSwipeSuccessful = 1)
AND a1.accessoverridereasonid IS NULL
AND a1.AttendDate BETWEEN #Start AND #End
group by a1.contactguid
)atc
outer APPLY
(
SELECT a2.contactguid, COUNT(*) TotalOverrideVisits
FROM Attendance a2
WHERE a2.contactguid = c.guid
And (a.IsSwipeSuccessful = 1)
AND a2.accessoverridereasonid IS NOT NULL
AND a2.AttendDate BETWEEN #Start AND #End
and (a2.SiteID = #SiteID OR #SiteID = 0)
group by a2.contactguid
) att
OUTER APPLY
(
SELECT a3.contactguid,COUNT(*) TotalOverrideDenieds
FROM Attendance a3
WHERE a3.contactguid = c.guid
AND a3.IsSwipeSuccessful = 0
AND a3.accessoverridereasonid IS NULL
AND a3.AttendDate BETWEEN #Start AND #end
group by a3.contactguid
) att1
where (a.SiteID = #SiteID OR #SiteID = 0)
and a.AttendDate BETWEEN #Start AND #End
GROUP BY atc.totalaccepted, att.TotalOverrideVisits, att1.TotalOverrideDenieds, ast.Name, c.FirstName + ' ' + c.LastName, md.MemRefNo) TB
ORDER BY MemRefNo
Since, you don't want the SUM of the values, then you can do something as above which basically embeds your SELECT as a subquery and then has a CASE statement to see whether the Total Values is greater than 0, if so return 1 else 0.

Counting records with a specific date value

I want to get all records entered with specific day, for example today:
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
#date nvarchar = '2012-09-21'
AS
BEGIN
declare #dateStart nvarchar(50) = #date + ' 00:00:00.0'
declare #dateEnd nvarchar(50) = #date + ' 23:59:59.437';
declare #returnData table (allQueue int,inQueue int,outQueue int)
SELECT 'table1' as table_name, COUNT(*)
FROM Queue as Counts
UNION ALL
SELECT 'table2' as table_name,COUNT(*) FROM Queue as Counts
WHERE QueueDate BETWEEN #dateStart AND #dateEnd
AND QueueNumIn != 0
END
Edited :
I Edited my code now it works :
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
AS
BEGIN
declare #date2 datetime
set #date2= '2012-09-21'
SELECT 'AllQueue' as table_name, COUNT(*)
FROM Queue as sdfds
UNION ALL
SELECT 'InQueue' as table_name,COUNT(*)
FROM Queue as sdfds
WHERE QueueDate >=#date2
AND QueueNumIn != 0
UNION ALL
SELECT 'OutQueue' as table_name, COUNT(*) FROM Queue as sdfds
WHERE QueueDate >=#date2
AND QueueNumOut != 0
END
It returns three records:
One problem is that the second column has no name. Why? Also, I want to return just one record that has three rows, not 3 separate records that have 2 fields.
you need to cast your varchar to datetime. and i think you want to assign Counts alias to Count(*)
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
#date nvarchar = '2012-09-21'
AS
BEGIN
declare #dateStart DATETIME = CAST(#date AS DATETIME)
declare #dateEnd DATETIME = DATEADD(hh,24,CAST(#date AS DATETIME))
declare #returnData table (allQueue int,inQueue int,outQueue int)
select 'table1' as table_name,COUNT(*) as Counts from QUEUE AS tb1
union all
select 'table2' as table_name,COUNT(*) as Counts from QUEUE AS tb2 where QueueDate >= #dateStart and QueueDate < #dateEnd and QueueNumIn !=0
END
not sure why returning all if you only want those in the spetial date.
Also, is better not to use between in Dates
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
#date datetime = '2012-09-21'
AS
BEGIN
select count(*) as 'AllQueue' ,
sum(case when QueueDate >=#date and QueueNumIn != 0 THEN 1 else 0 end) as 'InQueue',
sum(case when QueueDate >=#date and QueueNumOut != 0 THEN 1 else 0 end) as 'OutQueue'
from Queue
END
this should work.
this will give you something like
Allqueue inqueue, outqueue
----------------------------------------------------
11 | 8 | 10
This Code Worked and is edited code from ElVieejo
ALTER PROCEDURE [dbo].[SP_GET_QUEUESINFO_BY_DATE]
AS
BEGIN
declare #date2 datetime
set #date2= '2012-09-21'
select COUNT(QueueID) ,
sum(case when QueueNumIn != 0 THEN 1 else 0 end) as 'InQueue',
sum(case when QueueNumOut != 0 THEN 1 else 0 end) as 'OutQueue'
from Queue where QueueDate >= #date2
END