SELECT employees with count of finished tasks - sql

How would do the following in SQL:
"select all emps with list mark all one's tasks".................................
EmpId EmpName
------ --------
1 tom
2 jerry
3 jack
taskId EmpID mark
------ ----- ------
1 1 5
2 3 0
3 1 10
4 2 5
5 2 10
6 3 5
7 3 5
Result:
EmpName 0 5 10 sum
------ ----- ------ ------ ----
tom 0 1 1 2
jerry 0 1 1 2
jack 1 2 0 3

Try this:
SELECT e.EmpId, e.EmpName,
SUM(CASE WHEN t.mark = 0 THEN 1 ELSE 0 END) AS 0Mark,
SUM(CASE WHEN t.mark = 5 THEN 1 ELSE 0 END) AS 5Mark,
SUM(CASE WHEN t.mark = 10 THEN 1 ELSE 0 END) AS 10Mark,
COUNT(1) AS TotalMark
FROM employee e
INNER JOIN task t ON e.EmpId = t.EmpId
GROUP BY e.EmpId, e.EmpName;

select
e.empname,
(select count(*) from tasks t where e.empid=t.empid and mark=0) as mark0,
(select count(*) from tasks t where e.empid=t.empid and mark=5) as mark5,
(select count(*) from tasks t where e.empid=t.empid and mark=10) as mark10,
(select count(*) from tasks t where e.empid=t.empid) as marksum
from
employees e

It depends on your database engine - google "Pivot SQL " + your database engine (e.g. "pivot SQL MySQL").
The pivot feature means that you can convert values in the "mark" column to column headers, so if you have marks ranging from 0 to 100, you get one column for each value without having to create a subquery.
If your database engine doesn't support pivot, you may need to hard-code the columns in your resultset as #LajosVeres shows. I would add a "catch-all" subquery so if your data changes, you don't get illogical results, like so:
select
e.empname,
(select count(*) from tasks t where e.empid=t.empid and mark=0) as mark0,
(select count(*) from tasks t where e.empid=t.empid and mark=5) as mark5,
(select count(*) from tasks t where e.empid=t.empid and mark=10) as mark10,
(select count(*) from tasks t where e.empid=t.empid and mark not in (0, 5, 10)) as otherMarks,
(select count(*) from tasks t where e.empid=t.empid) as marksum
from
employees e

Related

Sqlite group by distinct count

I have table of customers operations:
date, client_id, gender
1 1 M
1 1 M
1 2 M
1 2 M
1 3 F
2 1 M
2 1 M
2 1 M
2 2 M
2 2 M
2 3 F
2 3 F
2 4 F
2 5 M
2 5 M
etc
Desired output is:
date, amount of males, (also need amount of females)
1 2 1
2 3 2
I need to group it by date, so i did it, then my goal is to find amount of each gender in each grouped group.
so i tried to do this to count amount of males:
sum(case when gender = 'M' then 1 else NULL end) as 'M%'
but its counted clients id 1 and 2 two times each, but i need to count it distinct.
On example above i expect this to return 2 because 2 male. But it return 4 because distinct construction doesnt work.
I tried this but it doesnt work and count '1' in result:
sum(distinct case when gender = 'M' then 1 else NULL end) as 'M%'
It's easier to count from the distinct rows of the table.
Also, use SQLite's feature to treat boolean expressions as 1 for true and 0 for false so you can sum them instead of using CASE expressions:
SELECT date,
SUM(gender = 'M') [amount of males],
SUM(gender = 'F') [amount of females]
FROM (SELECT DISTINCT date, client_id, gender FROM tablename)
GROUP BY date
See the demo.
You seem to want conditional count(distinct):
select date,
count(distinct case when gender = 'M' then client_id end) as count_m,
count(distinct case when gender = 'F' then client_id end) as count_f
from t
group by date;

How to get count based on column value that reset it in sql query

I want to get the count of column value but with conditional based on other column value.
ex: Below the data where first column is identity, second column statusId , third column repeat custId, fourth column status.
id statusId CustId status
1 1 100 E
2 1 100 E
3 1 100 E
4 2 100 S
5 1 100 E
6 1 100 E
7 2 100 S
8 1 200 E
9 1 200 E
10 2 200 S
11 2 200 S
12 1 200 E
13 2 200 S
I have used Row_Number() function but it didn't help to achieve it.
select case when Status = 'S' then 0
when Status = 'E' then sum(case when Status = 'E' then 1 else 0 end) over (order by Id asc) end as cnt
from cust
Expected Result: I want the result in below format using select query (not any loop).
CusId ExpectedCount
100 2 -- there are two rows with status E before last S
200 1 -- There is one row with status E before last S
To achieve above result, i am counting row that having status E and reset it back to 0 for status S and final count of status E should be returned prior last status S.
Actual result: I am getting count of Status value 'E' and count is not getting reset, its continue to count.
Ex.
custId Id Status ExpectedCount
100 1 E 1
100 2 E 2
100 3 E 3
100 4 S 0
100 5 E 4
100 6 E 5
100 7 E 6
THIS ANSWERS THE ORIGINAL VERSION OF THE QUESTION.
You can use a cumulative sum to define the groups and then use row_number():
select custid, id, status,
(case when status = 'S' then 0
else row_number() over (partition by custid, grp, status order by id)
end) as expectedcount
from (select t.*,
sum(case when status = 'S' then 1 else 0 end) over (partition by custid order by id) as grp
from t
) t;
Here is a db<>fiddle.

How to merge order by records from two different queries in SQL Server

Following scenario, in which I need top 3 records from the same table with specific condition and need to merge with second query records with excluding first query result.
Table A:
Id Name Flag
-------------
1 A 1
2 B 0
3 C 0
4 D 1
5 E 0
6 F 1
7 G 0
8 H 0
Top 3 where flag = 1 with latest records page index 1 and row count 5
Id Name Flag
----------------
6 F 1
4 D 1 first require flag =1 first 3 records
1 A 1
---------------------------------------
8 H 0
7 G 0
Page index 2 and row count 5 with latest records
Id Name Flag
--------------
6 F 1
5 E 0
3 C 0
2 B 0
How can I achieve this with a SQL query?
IF (#PageNumber = 0)
BEGIN
SELECT TOP (#RowsPerPage) [Id], [Name], [Flag]
FROM
(SELECT [Id], [Name], [Flag]
FROM
(SELECT TOP 3 [Id], [Name], [Flag]
FROM [A]
WHERE Flag = 1
ORDER BY Id DESC
UNION
SELECT [Id], [Name], [Flag]
FROM [A]
ORDER BY Id DESC) T
END
ELSE
BEGIN
// Normal paging query excluding top 3 flag records.
END
Try this
WITH CTE
AS
(
SELECT
Seq1 = ROW_NUMBER() OVER(PARTITION BY Flag ORDER BY Id DESC),
Seq2 = ROW_NUMBER() OVER(ORDER BY Id DESC),
Id,
Name,
Flag
FROM t1
)
SELECT
Seq1,
id,
name,
flag
FROM CTE
WHERE Seq1 < 4
UNION ALL
SELECT
Seq2,
id,
name,
flag
FROM CTE
WHERE Seq1 >3
ORDER BY 4 desc,1

SQL Query to fetch employee Attendence

I need to write query on employee table to fetch the employee with employee ID & how many days he is present absent & half-day for given date range.
Employee
AID EmpID Status Date
1 10 Present 17-03-2015
2 10 Absent 18-03-2015
3 10 HalfDay 19-03-2015
4 10 Present 20-03-2015
5 11 Present 21-03-2015
6 11 Absent 22-03-2015
7 11 HalfDay 23-03-2015
Expected Output will be :
EmpID Present Absent HalfDay
10 2 1 1
11 1 1 1
Can you please help me with the Sql query ?
Here Is the query I tried
SELECT EMP.EMPID,
(CASE WHEN EMP.STATUS = 'Present' THEN COUNT(STATUS) ELSE 0 END) Pres,
(CASE WHEN EMP.STATUS = 'Absent' THEN COUNT(STATUS) ELSE 0 END) ABSENT,
(CASE WHEN emp.status = 'HalfDay' THEN Count(status) ELSE 0 END) HalfDay
FROM EMPLOYEE EMP GROUP BY emp.empid
The COUNT() function tests if the value is NOT NULL. Therefore it will always increment for both sides of a CASE statement like this:
COUNT(CASE Status WHEN 'Present' THEN 1 ELSE 0) AS Present
So we need to use SUM() ...
select empid,
sum(case when status='Present' then 1 else 0 end) present_tot,
sum(case when status='Absent' then 1 else 0 end) absent_tot,
sum(case when status='HalfDay' then 1 else 0 end) halfday_tot
from employee
group by empid
order by empid
/
... or use COUNT() with a NULL else clause. Both produce the same output, perhaps this one is clearer:
SQL> select empid,
2 count(case when status='Present' then 1 end) present_tot,
3 count(case when status='Absent' then 1 end) absent_tot,
4 count(case when status='HalfDay' then 1 end) halfday_tot
5 from employee
6 group by empid
7 order by empid
8 /
EMPID PRESENT_TOT ABSENT_TOT HALFDAY_TOT
---------- ----------- ---------- -----------
10 2 1 1
11 1 1 1
SQL>
Note that we need to use ORDER BY to guarantee the order of the result set. Oracle introduced a hashing optimization for aggregations in 10g which meant GROUP BY rarely returns a predictable sort order.
Replace 0 with null because it would be also come in count and added the where clause for date range, check the example below:
select empID,
count(case when status='Present' then 1 else null end) Present_Days,
count(case when status='Absent' then 1 else null end) Absent_Days,
count(case when status='HalfDay' then 1 else null end) HalfDays
from Employee
where date >= to_date('17mar2015') and date <= to_date('23mar2015')
group by empID

select from 2 tables with multiple counts

I have 2 tables I'm trying to join in a select query.
Table 1: Store, primary_key(id,store_num)
store_id store_num due_date manager_id
1 100 06-30-2024 user1
2 108 06-30-2018 user2
3 109 13-31-2014 user3
Table 2: Department, where status(A-applied,p-Pending)
store_id store_num dept_num status
1 100 201 A
1 100 202 A
1 100 203 P
1 100 204 A
1 100 205 P
1 100 206 A
Expecting to select store_id, store_num, due_date, manager_id, Applied count, pending count. The result is something looks like this.
store_id store_num due_date manager_id applied_count pending_count
1 100 06-30-2024 user1 4 2
I tried it and got where I am able to join and get it in multiple rows, But counts not working out for me. can some one help me how I can get the counts
select
store.store_id,
store.store_num,
store.due_date,
store.manager_id,
dept.status
from store as store
inner join department as dept on store.store_id = dept.store_id
and store.store_num = dept.store_num
Your query is half way done. You need to do an aggregation to get the values in different columns. This is a conditional aggregation, as shown here:
select s.store_id, s.store_num, s.due_date, s.manager_id,
sum(case when d.status = 'A' then 1 else 0 end) as Active_Count,
sum(case when d.status = 'P' then 1 else 0 end) as Pending_Count
from store s inner join
department as dept
on s.store_id = d.store_id and s.store_num = d.store_num
group by store.store_id, store.store_num, store.due_date, store.manager_id;
The expression:
sum(case when d.status = 'A' then 1 else 0 end) as Active_Count,
Is counting the rows where status = 'A'. It does so by assigning such rows a value of 1 and then summing up that value.