I have asked similar question SQL Count non existing item.
But I need another point of view. Here is my different version of question.
I have table Groups,
ID NUMBER
STATUS VARCHAR2(20 BYTE)
OWNER VARCHAR2(20 BYTE)
I am able to count the number of status as following. (taking account owner tuple as well)
select g.owner, g.status, count(*) countRS from groups g group by g.owner, g.status order by g.owner ;
OWNER STATUS COUNTRS
-------------------- -------------------- ----------
JOHN NOK 1
JOHN OK 2
MARK OK 1
I have another status ,say PENDING, REJECTED. But there is no item exists in table, but I want them to be shown with zero count as following.
OWNER STATUS COUNTRS
-------------------- -------------------- ----------
JOHN NOK 1
JOHN OK 2
JOHN PENDING 0
JOHN REJECTED 0
MARK OK 1
MARK NOK 0
MARK PENDING 0
MARK REJECTED 0
This query below will get the cartesian product of unique owner on table group to the number of records of status. The result rows will then be joined on table groups so we can be able to count the number of status per owner.
SELECT a.owner, b.status,
COUNT(g.status) TotalCount
FROM (SELECT DISTINCT OWNER FROM groups) a
CROSS JOIN
(
SELECT 'NOK' `status` UNION ALL
SELECT 'OK' `status` UNION ALL
SELECT 'PENDING' `status` UNION ALL
SELECT 'REJECTED' `status`
) b
LEFT JOIN groups g
ON a.owner = g.owner
AND b.status = g.status
GROUP BY a.owner, b.status
ORDER BY a.owner, b.status
SQLFiddle Demo
Add a "Status" table to your DB. Change "Status" field in "Groups" table to "StatusId", which should link to that new table. Then in your select you can right join "Status" table, and this will give rows in query result for missing status too.
Related
I have a table like below.
The rule is, In each group, there is always one person with Code (>0), we can see that person as primary person in group.
In each group, if the primary person with Code > 0 and Status = "active", then we choose this record (Allen in group A).
However, if if the primary person with Code > 0 has Status != "active", then we need to seek other people in its group.
In group B, Amanda has Code but inactive so she is out, in the rest 3 people, the Status of Sarah has higher priority than Joe (Status priority: active -> pre_active -> pending -> inactive), so we choose Sarah and give her code with 2 (same as Amanda, the primary record in this group).
If there are multiple record in group that code = 0 and has same status, then we choose the one on top (by sequence).
In the end, I have to keep 1 record for each group, and give them code number from primary record if the selected record has code in 0.
Name
Code
Status
Group
Allen
8
active
A
Louis
0
inactive
A
Cindy
0
inactive
A
Joe
0
pending
B
Amanda
2
inactive
B
Sarah
0
pre_active
B
The result should be like below:
Name
Code
Status
Group
Allen
8
active
A
Sarah
2
pre_active
B
Thanks in advance!
I did it with two correlated queries, which would not be too efficient.
I also used GroupCode field name to avoid escaping the keyword.
In MySQL syntax:
SELECT Name,
(SELECT MAX(Code)
FROM YourTable tbl2
WHERE tbl1.GroupCode=tbl2.GroupCode) Code,
Status,
GroupCode
FROM YourTable tbl1
WHERE tbl1.Name = (SELECT Name
FROM YourTable tbl3
WHERE tbl1.GroupCode=tbl3.GroupCode
ORDER BY
-- active -> pre_active -> pending -> inactive
CASE Status
WHEN 'active' THEN 0
WHEN 'pre_active' THEN 1
WHEN 'pending' THEN 2
WHEN 'inactive' THEN 3
END
LIMIT 1);
DEMO Fiddle
I have a table with following rows :
SectionId
SectionStatus
1
Assigned
1
Approved
2
Assigned
2
Assigned
3
Assigned
Now I want to fetch the SectionId where al SectionStatus belong to that SectionId are not Approved.
Result expected for above table : 1,2,3
Another Example :
SectionId
SectionStatus
1
Approved
1
Approved
2
Assigned
2
Assigned
3
Assigned
Result expected for above table : 2,3
This looks like aggregation with a conditional count in the HAVING clause.
SELECT t.SectionId
FROM yourtable t
GROUP BY t.SectionId
HAVING COUNT(CASE WHEN t.SectionStatus = 'Approved' THEN 1 END) = 0;
db<>fiddle
One way to get that is by cross-applying the record and check whether that is 'Approved' or not.
Try the following:
select distinct SectionId from yourtable tab
cross apply (select 'Approved' Stat)t
where t.Stat <> tab.SectionStatus
Please see the db<>fiddle here.
I have Customer Appt table:
ID PK
CID FK
ApptDate
Status ( it could be; awaiting response, cancelled, did not attend, attended)
Customer Table:
CID PK
Name
SUrname
address etc.
every customer have multiple appointments booked and my task is finding the last appointment where status is not Attended And customer have not had any subsequent appts booked..
i've tried subquery but didn't work..also tried this:
select ID, CID, max(ApptDate)
from customer_appts
where status!= 'Attended'
this is not checking if there wasnt any subsequent appts booked.. I think i need to use if statement or nested.. if any one could direct me i'd be grateful
UPDATE:
Example: appt records for customer ID: 20 -- it should return last record date 23/20/20-- No subsequent appts booked after that date and status is not attended
ID CID Appt Date Status
1 20 27/01/20 Not Attended
2 20 30/01/20 Attended
3 20 23/02/20 cancelled
MORE EXAMPLES
ID CID Appt Date Status
1 30 27/01/20 Not Attended
2 30 30/01/20 Cancelled
3 30 23/02/20 Attended
for Customer 30 it should NOT return any records as after the 'Cancelled' appts we booked them an appointment and status is 'Attended'
I think you are trying to find out which client didn't have an appointment since the last time they missed one. Note that I've assumed id was an identity column and as good as the date for ordering.
Here's one way of doing it...
SELECT *
FROM customer_appts a
WHERE
status <> 'Attended'
AND NOT EXISTS (
SELECT 1
FROM customer_appts
WHERE cid = a.cid AND id > a.id
)
Here's another...
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY cid ORDER BY id DESC) AS ordering
FROM customer_appts
) a
WHERE
a.ordering = 1
AND status <> 'Attended'
SQL FIDDLE
my task is finding the last appointment where status is not Attended.
I think you want:
select a.*
from customer_appts a
where a.id = (select top (1) a2.id
from customer_appts a2
where a2.cid = a.cid and
a2.status <> 'Attended'
order by a2.ApptDate desc
);
I have to extract only those empid from a table whose status is both A and B only.
EMPID Status Number
1 A X
1 B Y
There are a number of ways to approach this query. One way is to verify that each employee does not have any status other than A or B associated with him, and that there are two distinct statuses associated with him. Note that the first condition being true means that the only two distinct statuses present must be A and B.
SELECT EMPID
FROM yourTable
GROUP BY EMPID
HAVING SUM(CASE WHEN Status NOT IN ('A', 'B') OR Status IS NULL THEN 1 ELSE 0 END) = 0 AND
COUNT(DISTINCT Status) = 2
Demo here:
Rextester
I have a table that records status on course progress. A new record is added for each user/course comination when a course is started. That record is updated with a 'completed' status when the course is completed. I need to find the records for users who have never completed any courses.
Example Table:
User Course Status
A 1 S
A 2 C
B 1 S
C 2 S
D 2 C
C 3 S
I need a query that finds the following:
User Course Status
B 1 S
C 2 S
C 3 S
Any help is appreciated.
select user, course, status
from your_table
where user in
(
select user
from your_table
group by user
having sum(CASE WHEN status = 'C' THEN 1 ELSE 0 END) = 0
)
Select User, Course, Status from MyTable where User not in (Select Distinct User from MyTable where Status = 'C')
SELECT User,Course,Status FROM YourTable a
LEFT JOIN
(SELECT DISTINCT User FROM YourTable WHERE Status='C') CompletedAnything
ON a.User=CompletedAnything.User
WHERE COmpletedAnything.User IS NULL
Here's a SQL Fiddle that gives you what you want:
http://sqlfiddle.com/#!2/b6988/1
Query is this:
select User, Course, Status
from mytable
where User not in
(select distinct User from mytable where status = 'C' ans User is not null)