i am updating an School Application in which i want to calculate absents of any student by their ID and selected time period. i have table in Sql Server named as CHECKINOUT that saves data of students. now i want to calculate absent of any student.when someone enters in school, an entry is made in this table with following fields
[USERID]
,[CHECKTIME]
,[CHECKTYPE]
this is screenshot of data in CHECKINOUT table
now say i have id 10 and i want to calculate absent of student during last month, i am confused in query. please help me in this
was working on it, not sure if this is the easiest but it works, i've tested it.
select missDates.userid, checkinout.userid, dt from
checkinout right join
(select * from (
SELECT DATEADD(DAY, nbr - 1, #StartDate) dt
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
FROM sys.columns c
) nbrs
WHERE nbr - 1 <= DATEDIFF(DAY, #StartDate, #EndDate)) alldates
cross join (select distinct userid from checkinout) t2) missDates
on missdates.userid = checkinout.userid
and convert(date,checktime) = convert(date,dt)
where checkinout.userid is null
Related
I have a table with Scheduling slots called:
ScheduleSlots
Fields:
id (int)
scheduleID (int)
time (datetime)
availableslots (int)
CalendarGroupID (int)
Level (int)
enabled (bit)
I want to setup a gridview where I take all of the dates and count enabled and disabled for each day.
I am not sure how to go about writing the sql statement to do this.
ie.
Date Enabled Disabled
3/31/2021 20 20
4/1/2021 10 30
SELECT Time, scheduleID,
(SELECT COUNT(Enabled) FROM [dbo].[ScheduleSlots]
WHERE Cast(Time as Date)>='2021-03-31' AND Cast(Time as Date)<='2021-04-01' AND CalendarGroupID=1 AND Level=1 AND Enabled=1) as Enabled,
(SELECT COUNT(Enabled) FROM [dbo].[ScheduleSlots]
WHERE Cast(Time as Date)>='2021-03-31' AND Cast(Time as Date)<='2021-04-01' AND CalendarGroupID=1 AND Level=1 AND Enabled=0) as Disabled
FROM [dbo].[ScheduleSlots]
WHERE Cast(Time as Date)>='2021-03-31' AND Cast(Time as Date)<='2021-04-01' AND CalendarGroupID=1 AND Level=1
GROUP BY scheduleID, Time
The results I end up with:
[Results][1]
You could do it without inner selects:
SELECT [Time],
SUM([Enabled]) as [Enabled],
SUM([Disabled]) as [Disabled]
FROM [dbo].[ScheduleSlots]
WHERE
[Time]>='2021-03-31'
AND [Time]<='2021-04-01'
AND CalendarGroupID=1
AND Level=1
GROUP BY Cast([Time] as Date)
It is an easy grouping query:
SELECT
CONVERT(DATE, "Time") AS "Date",
SUM(CONVERT(INT, "Enabled")) AS "Enabled",
COUNT() - SUM(CONVERT(INT, "Enabled")) AS "Disabled"
FROM "dbo"."ScheduleSlots"
WHERE "CalendarGroupID" = 1
AND "Level" = 1
GROUP BY CONVERT(DATE, "Time")
I hope I understand you correctly where you want the enable slot and diable slot for each day.
;With CTE(Transdate) as (Select Distinct([time]) from ScheduleSlots)
Select CTE.Transdate,(Select COUNT(Id) from ScheduleSlots where enabled= 1
and Transdate = CTE.Transdate) as Enable,
(Select COUNT(Id) from ScheduleSlots where enabled= 0
and Transdate = CTE.Transdate) as Disable from CTE
I inserted some records to make it clear. If I am wrong with inserted data please send me the insert scripts so, that I can test the results.
CREATE TABLE ScheduleSlots
(
id int,
scheduleID int,
[time] datetime,
availableslots int,
CalendarGroupID int,
[Level] int,
[enabled] bit
)
----insert into ScheduleSlots values(1,1,'2021-03-31',40,1,1,20)
INSERT INTO ScheduleSlots VALUES(1,1,'2021-03-31',20,1,1,0)
INSERT INTO ScheduleSlots VALUES(1,1,'2021-03-31',20,1,1,1)
INSERT INTO ScheduleSlots VALUES(1,1,'2021-03-31',20,1,1,1)
INSERT INTO ScheduleSlots VALUES(1,1,'2021-04-01',40,1,1,1)
INSERT INTO ScheduleSlots VALUES(1,1,'2021-04-01',40,1,1,0)
SELECT DISTINCT
[time] AS [Date]
,SUM(availableslots) OVER(PARTITION BY [time] ORDER BY [time]) AS [avaibale]
,SUM(CAST([enabled] AS INT)) OVER(PARTITION BY [time] ORDER BY [time]) AS [Enabled]
,SUM(availableslots) OVER(PARTITION BY [time] ORDER BY [time]) -
SUM(CAST([enabled] AS INT)) OVER(PARTITION BY [time] ORDER BY [time]) AS [Disabled]
FROM ScheduleSlots
Answer I got:
Blue is one employee name and red is another employee name. Here showing two rows but I want one row. I'm using
=Fields!EmpName.Value & Fields!LeaveDate.Value
expression how to show two rows of data into one row. That means blue row contains two leave types in one row
Used each row =Fields!EmpName.Value & Fields!LeaveDate.Value expression
CREATE PROCEDURE query
(#EmployeeIds varchar(8000),
#TenantId int)
AS
BEGIN
DECLARE #empIds TABLE (id int);
INSERT INTO #empIds
SELECT Id
FROM SplitStringToIntRows(#EmployeeIds, ',');
SELECT
et.LeaveDate AS LeaveDate, lt.Value AS LeaveType,
emp.FirstName + ' ' + emp.LastName AS EmpName,
emp.CustomEmployeeId AS CustomEmployeeId,
CONVERT(DATE, GETDATE()) AS StartDate,
DATEADD(month, 1, CONVERT (date, GETDATE())) AS EndDate
FROM
LeaveManagement.EmployeeLeaveTransaction et
INNER JOIN
LeaveManagement.LeaveMaster lm ON et.LeaveMasterId = lm.LeaveMasterId
INNER JOIN
Lookup.LeaveType lt ON lt.LeaveTypeId = lm.LeaveTypeId
INNER JOIN
HumanResource.Employee emp ON emp.EmployeeId = et.EmployeeId
INNER JOIN
#empIds empPar ON empPar.id = et.EmployeeId
WHERE
CONVERT(DATETIME, CAST(et.LeaveDate AS DATE), 110) >= CONVERT(DATE, GETDATE())
AND CONVERT(DATETIME, CAST(et.LeaveDate AS DATE), 110) <= DATEADD(month, 1, CONVERT (date, GETDATE()))
AND emp.TenantId = #TenantId
--AND lt.Value='No Pay Leave'
END
you must add "Fields!EmpName.Value " in the Group expressions of the row groups.
add EmpName field into your row groups. e.g. in below image i have grouped my data in HRIM field that i had.
I have a stored procedure that inserts a line in a table. This table has an auto incremented int primary key and a datetime2 column named CreationDate. I am calling it in a for loop via my C# code, and the loop is inside a transaction scope.
I run the program twice, first time with a for loop that turned 6 times and second time with a for loop that turned 2 times. When I executed this select on sql server I got a strange result
SELECT TOP 8
RequestId, CreationDate
FROM
PickupRequest
ORDER BY
CreationDate DESC
What I didn't get is the order of insertion: for example the line with Id=58001 has to be inserted after that with Id=58002 but this is not the case. Is that because I put my loop in a transaction scoope? or the precision in the datetime2 is not enough?
It is a question of speed and statement scope as well...
Try this:
--This will create a #numbers table with 1 mio numbers:
DECLARE #numbers TABLE(Nbr BIGINT);
WITH N(N) AS
(SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1)
,MoreN(N) AS
(SELECT 1 FROM N AS N1 CROSS JOIN N AS N2 CROSS JOIN N AS N3 CROSS JOIN N AS N4 CROSS JOIN N AS N5 CROSS JOIN N AS N6)
INSERT INTO #numbers(Nbr)
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM MoreN;
--This is a dummy table for inserts:
CREATE TABLE Dummy(ID INT IDENTITY,CreationDate DATETIME);
--Play around with the value for #Count. You can insert 1 mio rows in one go. Although this runs a while, all will have the same datetime value:
--Use a small number here and below, still the same time value
--Use a big count here and a small below will show a slightly later value for the second insert
DECLARE #Count INT = 1000;
INSERT INTO Dummy (CreationDate)
SELECT GETDATE()
FROM (SELECT TOP(#Count) 1 FROM #numbers) AS X(Y);
--A second insert
SET #Count = 10;
INSERT INTO Dummy (CreationDate)
SELECT GETDATE()
FROM (SELECT TOP(#Count) 1 FROM #numbers) AS X(Y);
SELECT * FROM Dummy;
--Clean up
GO
DROP TABLE Dummy;
You did your insertions pretty fast so the actual CreationDate values inserted in one program run had the same values. In case you're using datetime type, all the insertions may well occur in one millisecond. So ORDER BY CreationDate DESC by itself does not guarantee the select order to be that of insertion.
To get the desired order you need to sort by the RequestId as well:
SELECT TOP 8 RequestId, CreationDate
FROM PickupRequest
ORDER BY CreationDate DESC, RequestId DESC
My problem is that I want to start a database query which should give me the last (maxDate) entry of every Serial number.
I am working with a Microsoft SQL Server database.
The first picture shows all entries in the database:
After I have run the following code I get this output:
string aQuery = #" SELECT *
FROM (
SELECT SerialNumber, MAX(Date) as MaxDate
FROM eBox_Deploy
GROUP BY SerialNumber
) r
INNER JOIN eBox_Deploy t
ON t.SerialNumber = r.SerialNumber AND t.Date = r.MaxDate";
using (var db = new eBoxDataContext())
{
list.AddRange(db.ExecuteQuery<eBox_Deploy>(bQuery));
}
After picture:
Now my problem is that I have duplicates because they already exists in the database. Distinct doesn't work well because these all have different Id´s.
How can I get them away?
You could use windowed functions:
SELECT *
FROM (SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY [SerialNumber] ORDER BY [Date] DESC)
FROM eBox_Deploy) AS sub
WHERE rn = 1;
If your [Date] is not unique within SerialNumber group use RANK() to get ties.
My table structure is..
Id UserId EventId
1 1 A
2 1 B
3 1 C
4 1 A
5 1 D
The output I need..
UserId EventStart EventEnd
1 A B
1 B C
1 C A
1 A D
I want every two rows to be merged into a row, so if the first row has A and 2nd has B then the first row of result table has A & B..
I have looked into PIVOT but unable to figure out how to get the results I want..
It would be great if I could solve this with sql else if it has to be solved in the middle layer, I'm using C#
Any help is sincerely appreciated..
Thanks..
Assuming that you have have an id column that specifies the ordering, you can get what you want using lead() (in SQL Server 2012+):
select userId, eventid as eventstart,
lead(eventid) over (partition by userid order by id) as eventend
from mytable t;
You are filtering out the last row, which you can do with a subquery (window functions aren't allowed in the where clause):
select t.*
from (select userId, eventid as eventstart,
lead(eventid) over (partition by userid order by id) as eventend
from mytable t
) t
where eventend is null;
In earlier versions of SQL Server, you can get the same effect in other ways, such as a correlated subquery or cross apply. Here is an example:
select t.*
from (select userId, eventid as eventstart,
(select top 1 t2.eventid
from mytable t2
where t2.userid = t.userid and
t2.id > t.id
order by t2.id
) as eventend
from mytable t
) t
where eventend is not null;
An easy approach would be using a CTE with a generated Row_Number() over the ID and joining over UserID and Rownumber.
declare #t Table([ID] [int] IDENTITY(1,1) NOT NULL, UserID int,EventID varchar(10))
insert into #t
Select 1,'A'
UNION ALL Select 1,'B'
UNION ALL Select 1,'C'
UNION ALL Select 1,'A'
UNION ALL Select 1,'D'
UNION ALL Select 2,'B'
UNION ALL Select 2,'C'
UNION ALL Select 2,'A'
UNION ALL Select 2,'D'
;With c as
(
Select UserID,EventID,Row_Number() OVER (Order by UserID,ID ) as RN
from #t
)
Select c1.UserID,c1.EventID as EventStart ,c2.EventID as EventEnd
from c c1
Join c c2 on c2.RN=c1.RN+1 and c2.UserID=c1.UserID