Getting count of total present and absent in single sql query - mysql

Here is my attendance table details Emp_ID(varchar),pdate(datetime),attendance(char(2))
i want to get the total count of attendence days ,total count of absent and total count of present in a single query for a particular date range grouping by emp_id

just an sample example to show you how to proceed with your data
declare #t table (id int,da date,attend Varchar(2))
insert into #t (id,da,attend) values (1,'20141011','P'),
(1,'20141012','A'),
(1,'20141013','P'),
(1,'20141014','A'),
(1,'20141014','P')
select ID,COUNT(da)Total,
(select COUNT(da) from #t where attend = 'A')as Absent,
(select COUNT(da) from #t where attend = 'P')as Present from #t
group by id

this worked for me.
select Emp_ID
,count(case when status ='A' then 1 end) as absent_count
,count(case when status ='P' then 1 end) as present_count
,count(distinct pdate) as Tot_count
from MASTERPROCESSDAILYDATA where pdate between '2014-01-01' and '2014-01-31'
group
by Emp_ID ;

You should try something like that
SELECT Emp_id, present, absent FROM details
NATURAL JOIN(
SELECT COUNT(*) AS present FROM details WHERE Emp_id = table.Emp_id AND attendence='P'
JOIN
SELECT COUNT(*) AS absent FROM details WHERE Emp_id = table.Emp_id AND attendence='A' ) AS ctt

You could use group by, as already demonstrated.
Or you can use window functions/analytic functions.
DECLARE #T TABLE (Emp_id INT,pdate DATE,attendance VARCHAR(2))
INSERT INTO #t (emp_id,pdate,attendance) VALUES (1,'20141011','P'),
(1,'20141012','A'),
(1,'20141013','P'),
(1,'20141014','A'),
(1,'20141014','P')
SELECT
DISTINCT
EMP_ID,
Attendance,
COUNT(*) OVER (PARTITION BY attendance) as CntAttendance
FROM
#t

Try the script below;
select id,
count(distinct pdate) as Total_Attendance_Days,
sum(case when attendance= 'p' then 1 else 0 end) Presents,
sum(case when att = 'a' then 1 else 0 end) Absents
from ##TT
where pdate between '01/04/2015' and '15/04/2015'
group by id
Hope this helps

Related

Summing of count result at same level

I'm trying to sum the results of count(id) at the same level, in order to find out the relative portion of the count(id) from the overall count.
The count is grouped by the respective previous number, and I want to stay at the same table and have it all together.
`
select totalattempts, count(totalattempts) allattempts, count(case when success>0 then totalattempts else null end) successfulattempts
from (
select *, case when success> 0 then attemptspresuccess+1 else attemptspresuccess end totalattempts
from (select orderid, count(orderid) attemptspresuccess, count(case when recoveredPaymentId is not null then recoveredPaymentId end ) success from (
select orderid, recoveredPaymentId
from errors
where platform = 'woo'
) alitable
group by orderid) minitable ) finaltable
group by totalattempts
order by totalattempts asc
`
I need to add another column that basically would have, to put it simply, count(totalattempts)/sum(count(totalattempts).
I'm running out of ideas basically.
I can't use windows as this is an app of retool which doesn't support that
Assuming some test data here:
DECLARE #table TABLE (AttemptNumber INT IDENTITY, Success BIT)
INSERT INTO #table (Success) VALUES
(0),(0),(0),(0),(1),(1),(0),(0),(0),(0),(0),(1),(0),(1),(0),(0),
(0),(0),(1),(0),(0),(0),(0),(1),(0),(1),(0),(0),(0),(1),(0),(0)
I sounds like you want to know how many attempts there were, how many were successful and what that is a percentage?
SELECT COUNT(Success) AS TotalCount,
COUNT(CASE WHEN Success = 1 THEN 1 END) AS SuccessCount,
COUNT(CASE WHEN Success = 1.0 THEN 1 END)/(COUNT(Success)+.0) AS SuccessPct
FROM #table
TotalCount SuccessCount SuccessPct
--------------------------------------
32 8 0.2500000000000

Get the student result from status when grouping in mysql

I have created a temporary table from records which looks like below. I want to group student using student id (stu_D). While grouping student result status will be PASSED if he passed all the subject and FAILED if he failed at least one.thanks in advanced
You can try below query -
SELECT stu_D
,stuName
,CASE
WHEN T2.CNT = 0
THEN 'passed'
ELSE 'failed'
END status
FROM (SELECT stu_D
,stuName
,COUNT(CASE
WHEN result = 'FAILED'
THEN 1
END) CNT
FROM T
GROUP BY stu_D
,stuname) T2
SELECT
T.stu_D, T.stuName, IF(T.number_of_failures>0, 'FAILED', 'PASSED') final_result
FROM
(SELECT
stu_D, stuName, COUNT(IF(result='FAILED', 1, NULL)) number_of_failures
FROM your_table
GROUP BY stu_D, stuName) T;
try this query
SELECT stu_Name,result
FROM `marks`
WHERE stu_D not in
(SELECT stu_D FROM marks WHERE result='FAILED')
GROUP BY stu_D

get value of columns in previous row and add to the next columns of the next row

I will create a graph of population by gender every year, and the graph looks like the image below.
But I'm having a hard time with the query.
Query
SELECT
year_added,
COUNT(case when gender='Male' then 1 end) as malecount,
COUNT(case when gender='Female' then 1 end) as femalecount,
COUNT(*) as totalcount
FROM tbl
WHERE status = 1
GROUP BY year_added
Result
In the result, 2016 male count is 4 and female count is 8. In 2017, I want the male count of 2016 to be added on the male count on 2017, meaning 2017 male count will be 5, same with female count and total count. I provided an image below of what the result should look like. Can you help me how to do this for me to proceed on doing the graph? Or is there any other way to achieve this?
Try this:
SELECT
year_added,
#malecount_v := #malecount_v + malecount as malecount,
#femalecount_v := #femalecount_v + femalecount as femalecount,
#totalcount_v := #totalcount_v + totalcount as totalcount
FROM (
SELECT
year_added,
COUNT(case when gender='Male' then 1 end) as malecount,
COUNT(case when gender='Female' then 1 end) as femalecount,
COUNT(*) as totalcount
FROM tbl
WHERE status = 1
GROUP BY year_added
ORDER BY year_added
) t1
CROSS JOIN (SELECT #malecount_v := 0, #femalecount_v := 0, #totalcount_v := 0) t2
In Mysql you can do it with variables, like:
SELECT
year_added,
(#iMalecount := (COUNT(CASE WHEN gender = 'Male' THEN 1 END) + #iMalecount)) AS malecount,
(#iFemalecount := (COUNT(CASE WHEN gender = 'Female' THEN 1 END) + #iFemalecount)) AS femalecount,
(#iTotalcount := (COUNT(gender) + #iTotalcount)) AS totalcount
FROM tbl
WHERE status = 1
GROUP BY year_added
but is not 100% fiable as you can read in the documentation.
In other SQL flavour probably you need a stored procedure.
you can simply use
WITH TableCount AS
(
SELECT
year_added,
COUNT(case when gender='Male' then 1 end) as malecount,
COUNT(case when gender='Female' then 1 end) as femalecount,
COUNT(*) as totalcount
FROM tbl
WHERE status = 1
GROUP BY year_added
)
And after that use following query
SELECT
SUM(malecount) as 'malecount',
SUM(femalecount) as 'femalecount',
SUM(totalcount) as 'totalcount'
FROM TableCount
If you are using MySql you can use temporary table to do something like CTE
CREATE TEMPORARY TABLE IF NOT EXISTS TableCount AS (
SELECT
year_added,
COUNT(case when gender='Male' then 1 end) as malecount,
COUNT(case when gender='Female' then 1 end) as femalecount,
COUNT(*) as totalcount
FROM tbl
WHERE status = 1
GROUP BY year_added
)
And then you can use above query
SELECT
SUM(malecount) as 'malecount',
SUM(femalecount) as 'femalecount',
SUM(totalcount) as 'totalcount'
FROM TableCount
You can use the TEMPORARY keyword when creating a table. A TEMPORARY
table is visible only to the current session, and is dropped
automatically when the session is closed. This means that two
different sessions can use the same temporary table name without
conflicting with each other or with an existing non-TEMPORARY table of
the same name. (The existing table is hidden until the temporary table
is dropped.) To create temporary tables, you must have the CREATE
TEMPORARY TABLES privilege.
By using temporary table concept you can achieve common table expression kind of functionality in MySql

How to select rows as a column for View in TSQL?

Assume I have 3 tables: Animal, CareTaker, and Apppointment. Schema, with some data like so:
Create Table Animal (Id int identity, Name varchar(25))
Create Table CareTaker(Id int identity, Name varchar(50))
Create Table Appointments(Id int identity, AnimalId int, CareTakerId int, AppointmentDate DateTime, BookingDate DateTime)
Insert into Animal(Name) Values('Ghost'), ('Nymeria'), ('Greywind'), ('Summer')
Insert into CareTaker(Name) Values ('Jon'), ('Arya'), ('Rob'), ('Bran')
Insert into Appointments(AnimalId, CareTakerId, AppointmentDate, BookingDate) Values
(1, 1, GETDATE() + 7, GetDate()), -- Ghost cared by Jon
(1, 2, GETDATE() + 6, GetDate()), -- Ghost cared by Arya
(4, 3, GETDATE() + 8, GetDate()) -- Summer cared by Rob
I want to select only 3 caretakers for each animal as a columns. Something like this:
I don't care about other appointments, just the next three, for each animal. If there aren't three appointments, it can be blank / null.
I'm quite confused about how to do this.
I tried it with Sub queries, something like so:
select Name,
-- Care Taker 1
(Select Top 1 C.Name
From Appointments A
Join CareTaker C on C.Id = A.CareTakerId
Where A.AppointmentDate > GETDATE()
And A.AnimalId = Animal.Id
Order By AppointmentDate) As CareTaker1,
-- Appointment Date 1
(Select Top 1 AppointmentDate
From Appointments
Where AppointmentDate > GETDATE()
And AnimalId = Animal.Id
Order By AppointmentDate) As AppointmentDate1
From Animal
But for the second caretaker, I would have to go second level select on where clause to exclude the id from top 1 (because not sure how else to get second row), something like select top 1 after excluding first row id; where first row id is (select top 1) situtation.
Anyhow, that doesn't look like a great way to do this.
How can I get the desired output please?
You can get all the information in rows using:
select an.name as animal, ct.name as caretaker, a.appointmentdate
from appointments a join
animals an
on a.id = an.animalid join
caretaker c
on a.caretakerid = c.id;
Then, you basically want to pivot this. One method uses the pivot keyword. Another conditional aggregation. I prefer the latter. For either, you need a pivot column, which is provided using row_number():
select animal,
max(case when seqnum = 1 then caretaker end) as caretaker1,
max(case when seqnum = 1 then appointmentdate end) as appointmentdate1,
max(case when seqnum = 2 then caretaker end) as caretaker2,
max(case when seqnum = 2 then appointmentdate end) as appointmentdate2,
max(case when seqnum = 3 then caretaker end) as caretaker3,
max(case when seqnum = 3 then appointmentdate end) as appointmentdate3
from (select an.name as animal, ct.name as caretaker, a.appointmentdate,
row_number() over (partition by an.id order by a.appointmentdate) as seqnum
from appointments a join
animals an
on a.id = an.animalid join
caretaker c
on a.caretakerid = c.id
) a
group by animal;

multiple select on stored procedure

I'm trying to do multiple selects from one table but it only shown the last select statement.
CREATE PROCEDURE `usp_GetStockCard` (IN Matecode varchar(10))
BEGIN
(select tran_date as tran_date
from TM_matbalance
where Mate_code=Matecode);
(select Mate_code as Mate_code
from TM_matbalance
where Mate_code=Matecode);
(select tran_qtyx as Qty_in
from TM_matbalance
where tran_type='IN'
and mate_code=matecode);
(select tran_qtyx as Qty_out
from TM_matbalance
where tran_type='OUT'
and mate_code=matecode);
END
I've tried to change semicolon to comma after each select statement but it said that syntax error: missing 'semicolon'.
please help.
I look at your problem and I think I solve it.
Basically there is two problems here first one is to pivot your table where your Tran_Qtyx column become Qty_In and Qty_Out based on value in Tran_Type column (IN or OUT)... That part of problem you solve with this query
SELECT Tran_Date, Mate_Code,
SUM(CASE WHEN Tran_Type = 'IN' THEN Tran_Qtyx ELSE 0 END) Qty_In,
SUM(CASE WHEN Tran_Type = 'OUT' THEN Tran_Qtyx ELSE 0 END) Qty_Out
FROM myTable
WHERE Mate_Code = 'MAT001'
GROUP BY DATE(Tran_Date)
NOTE: In your desired result I only see 'MAT001'as Mate_Code so I stick with that in this solution and exclude MAT002 from result.
More about pivot table you can read here, there you can find a link, which is good to take a look, and where you can find a lot of stuff about mysql query's.
The second part of your problem is to get Qty_Balance column. Similar problem is solved here. It's how to calculate row value based on the value in previous row.
So your complete query could look like this:
SELECT t1.Tran_Date, t1.Mate_Code, t1.Qty_In, t1.Qty_Out,
#b := #b + t1.Qty_In - t1.Qty_Out AS Qty_Balance
FROM
(SELECT #b := 0) AS dummy
CROSS JOIN
(SELECT Tran_Date, Mate_Code,
SUM(CASE WHEN Tran_Type = 'IN' THEN Tran_Qtyx ELSE 0 END) Qty_In,
SUM(CASE WHEN Tran_Type = 'OUT' THEN Tran_Qtyx ELSE 0 END) Qty_Out
FROM myTable
WHERE Mate_Code = 'MAT001'
GROUP BY DATE(Tran_Date)) AS t1
ORDER BY t1.Tran_Date;
NOTE: probably only think you should change here is table name and it's should work.
Here is SQL Fiddle so you can see how that's work!
GL!
You will need to structure your query into one, or pass in a parameter to the stored procedure to select which output/query you want, to restructure your query you will need something like:
`CREATE PROCEDURE `usp_GetStockCard` (IN Matecode varchar(10))
BEGIN
(select tran_date as tran_date, Mate_code as Mate_code, tran_qtyx as Qty
from TM_matbalance
where Mate_code=Matecode
and (tran_type='IN' or tran_type='OUT');
END`
Or try this if you have an ID column:
SELECT coalesce(ta.id, tb.id) as tran_id, coalesce(ta.tran_date, tb.tran_date) as tran_date, coalesce(ta.Mate_code, tb.Mate_code) as Mate_code, ta.tran_type as Qty_In, tb.tran_type as Qty_Out
from (select ta.*
from TM_matbalance ta
where ta.tran_type = 'IN'
and Mate_code=Matecode
) ta full outer join
(select tb.*
from TM_matbalance tb
where tb.tran_type = 'OUT'
and Mate_code=Matecode
) tb
on ta.id = tb.id ;
just replace "id" with the name of your ID column if you don't need to return the id column then remove coalesce(ta.id, tb.id) as tran_id