Tricky GROUP BY SQL with additional constraint - mysql

I have a "members" table like this:
id status user_id created_at
-----------------------------------
1 active 1 2015-07-01
2 active 2 2015-07-01
3 inactive 1 2015-07-04
4 deleted 2 2015-07-04
5 active 3 2015-07-04
6 active 1 2015-07-08
7 inactive 3 2015-07-08
How is it possible to query the latest status of all users at any given date?
For 2015-07-01 the output should be:
id status user_id created_at
-----------------------------------
1 active 1 2015-07-01
2 active 2 2015-07-01
For 2015-07-05 the output should be:
id status user_id created_at
-----------------------------------
3 inactive 1 2015-07-04
4 deleted 2 2015-07-04
5 active 3 2015-07-04
For 2015-07-10 the output should be:
id status user_id created_at
-----------------------------------
3 active 1 2015-07-08
4 deleted 2 2015-07-04
5 inactive 3 2015-07-08
Any help very much appreciated!

Use a group by with where to get the latest date before the given date, then a join:
select m.*
from members m join
(select user_id, max(created_at) as maxca
from members
where created_at <= '2015-07-08' -- or whatever
group by user_id
) mu
on m.user_id = mu.user_id and m.created_at = mu.maxca;

Related

How to join to single row in one to many relationship in SQL?

I want to join one to many table with single row on many table by limit 1 and order by create date
tbl_cart :
id fullname
1 myname1
2 myname2
3 myname3
tbl_cart_status:
id cart_id status created_at
1 1 33 2018-09-20
2 1 34 2018-09-23
3 2 34 2018-09-21
4 1 100 2018-09-25
5 2 35 2018-09-29
How can i get output with sql like this:
I want to get lastest status of my cart by ordered with created_at column
myname cart_id status created_at
myname1 1 100 2018-09-25
myname2 2 35 2018-09-29
Think filtering for this type of query:
select c.name, cs.*
from tbl_cart c join
tbl_cart_status cs
on c.id = cs.cart_id
where cs.created_at = (select max(cs2.created_at)
from tbl_cart_status cs2
where cs2.cart_id = cs.cart_id
);

MySQL percentage of values in a GROUP BY query

Let's say, I have 3 tables: appointments, doctors and departments.
appointments:
id status doctor_id
---- --------- ---------
1 approved 1
2 cancelled 4
3 approved 4
4 approved 1
5 approved 4
6 NULL 5
7 approved 2
8 NULL 5
9 approved 4
10 approved 3
11 cancelled 1
12 NULL 4
13 approved 3
14 cancelled 1
15 approved 4
16 cancelled 4
17 cancelled 2
18 NULL 4
19 cancelled 1
20 cancelled 4
doctors:
id name department_id
---- --------- -------------
1 John 1
2 Robert 2
3 Patricia 3
4 Mary 1
5 Susan 3
departments:
id name
---- ---------
1 Dermatology
2 Neurology
3 Radiology
What I need is percentage of approved appointments to total of approved and cancelled (approved / (approved + cancelled) * 100) in Dermatology department, grouped by doctors.
I used the following query, which got me closer to solution.
SELECT COUNT(*) AS appointment_count,
doctors.name AS doctor_name,
appointments.status AS appointment_status
FROM appointments
LEFT JOIN doctors ON appointments.doctor_id = doctors.id
LEFT JOIN departments ON doctors.department_id = departments_id
WHERE departments.id = 1
GROUP BY doctors.id,
appointments.status
result:
count doctor_name appointment_status
----- ----------- ---------
2 John approved
3 John cancelled
0 John NULL
4 Mary approved
3 Mary cancelled
2 Mary NULL
But I need the percentage of approved / (approved + cancelled) for each doctors. So the result should be:
approved_percentage doctor_name
------------------- -----------
%40 John
%57 Mary
How can I achieve such a result?
In MySQL, the simplest way to do conditional counts and averages is simply to use the boolean expression. This suggests:
SELECT d.name, count(*),
SUM(a.status = 'approved') as approved_count,
AVG(a.status = 'approved') * 100 as approved_percentage
FROM doctors d INNER JOIN
appointments a
ON a.doctor_id = d.id
GROUP BY d.name;
You can group only by doctors and then use count(if()) functionality like this:
SELECT d.name, count(*), count(if(a.status = 'approved', 1, null)) approved_count,
count(if(a.status = 'approved', 1, null))/count(*) * 100 approved_percentage
FROM doctors d
INNER JOIN appointments a ON a.doctor_id = d.id
GROUP BY d.name

MySQL Group By 2 adjacent Dates

I have one table named viewlist as follows
Id article_id viewdate
--------------------------------------------------
1 1 2015-07-01
2 1 2015-07-01
3 1 2015-07-01
4 2 2015-07-01
5 2 2015-07-01
6 1 2015-07-02
7 2 2015-07-02
8 1 2015-07-03
9 2 2015-07-03
10 1 2015-07-05
11 1 2015-07-05
----------------------------------------------------
i need to write a MySQL query to get count and article_id by grouping adjacent viewdate field
wanted result as follows
article_id count date_period
-----------------------------------------------------------------
1 4 2015-07-01 - 2015-07-02
2 3 2015-07-01 - 2015-07-02
1 1 2015-07-03 - 2015-07-04
2 1 2015-07-03 - 2015-07-04
1 2 2015-07-05 - 2015-07-06
Is there any simple query to get this type of result?
you may use something on these lines
SELECT v.article_id, COUNT(*), CONCAT(b.dt, ' - ', b.dt2) as 'date_period'
FROM viewlist v INNER JOIN
(SELECT a.dt, DATE_ADD(a.dt, INTERVAL 1 DAY) AS dt2 FROM (SELECT DISTINCT(viewdate) AS dt FROM viewlist WHERE (DAY(viewdate) MOD 2) = 1) a) b ON v.viewdate BETWEEN b.dt AND b.dt2
GROUP BY 1, 3
ORDER BY b.dt

Get status based on other table column value mysql

I have two tables.
job_table.
job_id job_type job_type User job_time job_name
1 1 Day User1 2015-04-23 23:20:10 Job1
2 2 Night User2 2015-04-23 13:20:10 Job2
3 3 Day & Night. User3 2015-04-22 23:10:10 Job3
4 3 Day & Night. User3 2015-04-20 13:40:10 Job4
5 1 Day User4 2015-04-26 03:20:10 Job5
and task_entry table.
task_entry_id job_id task_option_type emp_id completed_task_count status
1 1 Day 101 10 1
2 1 Day 102 0 0
3 1 Day 103 5 1
4 2 Night 101 20 1
5 3 Day 101 4 1
5 3 Night 101 0 0
6 3 Day 102 10 1
7 3 Night 102 5 1
If job_type of job_table is 3 then there will be 2 entries in task_entry table one for Day and one for Night.
Else only one entry.
That is if job_type is 3 then count should be count/2. (Day&Night).
Else count should be normal count.
I want to get the status based on the job_id. If all task_entry for a job_id is 1 then status should be 'COMPLETE' else 'PENDING'
and total completed_task_count.
job_id task_entry_count status completed_task_count
1 3 PENDING 15
2 1 COMPLETE 20
3 2 PENDING 19
How can i get that.
try this query
select job_id,count(task_entry_count),case when a.job_id is null then 'Compeletd' else 'pending'end as status,sum(completed_task_count)
from task_table
join (select job_id from task_table where status=0) a a.job_id =task_table.job_id
group by job_id

Check value in rows with same FK

I have the table below
ID | PARCEL | STATUS | ORDER_ID
1 1 COMPLETE 1234
2 2 COMPLETE 1234
3 1 COMPLETE 9999
4 2 PENDING 9999
5 3 PENDING 9999
6 1 COMPLETE 1111
7 2 COMPLETE 1111
8 3 COMPLETE 1111
9 1 COMPLETE 3333
10 2 PENDING 3333
I need select the order_id with ALL PARCEL's having a COMPLETE status.
i am trying with select, but don't work
SELECT * FROM table WHERE order_id NOT IN
(SELECT order_id FROM table WHERE status = 'COMPLETE');
the answer for the query is
ID | PARCEL | STATUS | ORDER_ID
1 1 COMPLETE 1234
2 2 COMPLETE 1234
6 1 COMPLETE 1111
7 2 COMPLETE 1111
8 3 COMPLETE 1111
You can use NOT EXISTS clause, so it will skip any order_id that has status other than COMPLETE
SELECT * FROM tableA A1
WHERE NOT EXISTS
( SELECT 1 from tableA A2
where A1.order_id= A2.order_id
and A2.status <> 'COMPLETE'
)
select * from table_parcels where STATUS like 'COMPLETE';