I have 3 mysql tables:
appointments
id slot_id patient_name doctor_id deleted_at
1 11 Tasin 23 2019-10-10
2 12 Nawaz 22 null
3 13 Rakib 23 null
4 14 Hossen 23 null
5 15 Aritra 24 null
6 16 Anik 22 null
7 17 Manik 22 null
doctors
id status doctor_name
22 1 Khaled
23 1 Hasan
24 0 Rumi
slots
id date duration time
11 2019-10-10 2900 01:01
12 2019-10-11 1200 02:01
13 2019-10-18 1100 03:01
14 2019-09-08 200 11:01
15 2019-08-01 500 01:31
16 2019-10-07 300 02:31
17 2019-10-02 1200 03:31
Now, I want to show a list of doctors with their total appointment durations in decreasing order using SQL query.
Unfortunately, I don't have any idea about this SQL query. Can you assist me?
SELECT DOCTOR_NAME, SUM(DURATION) FROM APPOINTMENTS A
JOIN DOCTORS D ON D.ID = A.DOCTOR_ID
JOIN SLOTS S ON S.ID = A.SLOT_ID
GROUP BY D.ID, DOCTOR_NAME
ORDER BY SUM(DURATION) DESC;
select d.doctor_id, d.doctor_name, sum(apt.duration) as total_duration from
doctors as d
join appointments as apt on apt.doctor_id = d.doctor_id
join slots as s on s.id = apt.slot_id
group by d.doctor_id, d.doctor_name
The above query should work fine.
There might be some typo as I didn't write it in the SQL management studio.
Related
I'm trying to get the list of IDs of all the rows with latest posting date for each author in a table, for example:
id author_id date
1 12 2020-12-23
2 12 2021-01-06
3 12 2021-04-12
4 12 2021-02-10
5 17 2021-09-16
6 17 2021-05-20
7 17 2021-02-23
8 17 2021-07-02
9 24 2021-03-24
10 24 2021-02-10
11 24 2020-08-18
12 24 2020-12-14
The desired result should be:
id
3
5
9
I used this query and it works perfect:
SELECT a.id
FROM (
SELECT author_id, MAX(`date`) as MaxDate
FROM `posts_log`
GROUP BY author_id
) b
INNER JOIN `posts_log` a
ON a.author_id = b.author_id AND a.date = b.MaxDate
But let's imagine that situation changed. Now author is allowed to post only once per month. So the table changed too and 'date' column became separated:
id author_id month year
1 12 12 2020
2 12 1 2021
3 12 4 2021
4 12 2 2021
5 17 9 2021
6 17 5 2021
7 17 2 2021
8 17 7 2021
9 24 3 2021
10 24 2 2021
11 24 8 2020
12 24 12 2020
Yeah, I know, looks a little bit stupid, but this wasn't my decision. Now I have such table and I'm not allowed to change the structure.
The question is: How to get the same result with this new table. Is it possible in MySQL?
You can use similar logic. Just instead of the date, use a calculated value from year and month:
SELECT a.id
FROM (
SELECT p.author_id, MAX(p.year*100+p.month) as MaxMonth
FROM posts_log p
GROUP BY p.author_id
) b
INNER JOIN posts_log a
ON a.author_id = b.author_id AND a.year*100+a.month = b.MaxMonth;
I have a table called play_progress.
play_progress
id user_id coins timecreated
1 1 20 2016-01-23 06:55:09
2 1 24 2016-01-23 06:59:22
3 1 28 2016-01-23 07:05:34
4 2 4 2016-01-23 07:10:58
5 2 10 2016-01-23 07:12:08
6 1 32 2016-01-24 00:07:48
7 2 14 2016-01-24 00:12:08
8 1 35 2016-01-24 00:44:48
9 2 18 2016-01-24 00:55:08
I like to get the latest row( based on timecreated) for each day for each user.
I have tried the following query;
SELECT user_id, coins, MAX(timecreated)
FROM player_progress
GROUP BY user_id, DATE(timecreated);
It gives the result for each day but it gives wrong timecreatd value.
Where I am going wrong?
Result details like
id user_id coins timecreated
1 1 28 2016-01-23 07:05:34
5 2 10 2016-01-23 07:12:08
8 1 35 2016-01-24 00:44:48
9 2 18 2016-01-24 00:55:08
I have searched through SO, but couldn't find a solution to my problem.
If you need to fetch more columns then the ones used for grouping (user_id and timecreatd) you need a more complex query:
SELECT p.user_id, p.id, coins, p.timecreated
FROM play_progress p INNER JOIN
(SELECT user_id, MAX(timecreated) as max_time
FROM play_progress
GROUP BY user_id, DATE(timecreated)) pp
ON p.user_id = pp.user_id
AND p.timecreated = pp.max_time;
Here you have a sample
Here is my table
loan_id bid_id lender_id borrower_id amount interest duration loan_status
1 1 60 63 300.00 12.00 3 'completed'
2 2 61 63 300.00 12.00 3 'completed'
3 3 62 63 300.00 12.00 3 'pending',
4 1 62 63 300.00 12.00 3 'pending'
7 4 60 63 300.00 12.00 3 'completed'
I want to pull only those bid_id whose loan_status of all records is completed. It means if there is any record of bid_id with status pending then it will not pull that record.
I am using the followin query that is working fine:
SELECT bid_id
FROM loan
WHERE bid_id NOT IN (
SELECT l.bid_id
FROM loan l
WHERE l.`loan_status` = 'pending'
AND l.bid_id = bid_id
GROUP BY l.`bid_id`
HAVING COUNT(l.`bid_id`)>= 1
)
GROUP BY bid_id
Is there any other way in which we can get desired result without using sub query.
You can readily do this with group by and having:
select bid_id
from loan
group by bid_id
having sum(loand_status = 'pending') = 0
I want to count the number of records in two tables, and group them together based on the dates from one of the counted tables.
At the moment, I have this query:
SELECT COUNT(DISTINCT efu.id) AS TotalCollections, COUNT(DISTINCT ccs.id) AS TotalCases, efu.completion_date
FROM enviro_figures_upload efu
LEFT JOIN customer_cases_upload ccs ON ccs.customer_site = efu.customer_site
WHERE efu.customer_site = "TGI Friday's Glasgow"
GROUP BY DATE_FORMAT(efu.completion_date, '%m-%Y') DESC
ORDER BY YEAR(efu.completion_date) ASC, MONTH(efu.completion_date) ASC
Which outputs the following results:
TotalCollections TotalCases completion_date
52 8 2014-05-21
73 8 2014-06-23
83 8 2014-07-02
89 8 2014-08-22
87 8 2014-09-21
68 8 2014-10-06
85 8 2014-11-20
59 8 2014-12-10
17 8 2015-01-05
However, the TotalCases column isn't being counted properly. There are 8 records altogether in that table, but in the query the number of cases should be counted based on the date (also called completion_date). There will be cases that TotalCases will return 0, but should be included against the TotalCollections and completion_date.
So really it should be:
TotalCollections TotalCases completion_date
52 2 2014-05-21
73 1 2014-06-23
83 1 2014-07-02
89 0 2014-08-22
87 0 2014-09-21
68 1 2014-10-06
85 0 2014-11-20
59 2 2014-12-10
17 1 2015-01-05
How can I do this?
EDIT
Here is some sample data from the enviro_figures_upload table:
id completion_date
124114 2014-09-30
124134 2014-10-31
124146 2014-05-23
124148 2014-05-24
124149 2014-05-26
124150 2014-05-27
124151 2014-05-28
124152 2014-05-25
124153 2014-05-29
124193 2014-05-31
124194 2014-05-24
124195 2014-05-26
124196 2014-05-27
124197 2014-05-28
Here is some sample data from the customer_cases_upload:
id completion_date
2519 2014-10-17
2520 2014-12-15
2521 2014-07-28
2522 2014-12-12
2523 2014-09-27
2524 2014-11-03
2525 2014-05-30
2526 2014-05-22
TotalCases is showing 8 because there is no constraint on customer_cases_upload.completion_date.
Try:
SELECT COUNT(DISTINCT efu.id) AS TotalCollections, COUNT(DISTINCT ccs.id) AS TotalCases, efu.completion_date
FROM enviro_figures_upload efu
LEFT JOIN customer_cases_upload ccs ON ccs.customer_site = efu.customer_site
and year(efu.completion_date) = year(css.completion_date)
and month(efu.completion_date) = month(css.completion_date)
WHERE efu.customer_site = "TGI Friday's Glasgow"
GROUP BY DATE_FORMAT(efu.completion_date, '%m-%Y')
ORDER BY YEAR(efu.completion_date) ASC, MONTH(efu.completion_date) ASC
I'm not quite sure what the customer_site column is, as the column is not included in your sample data, but I think your LEFT JOIN needs to be more specific. It looks like there are 8 total records in the customer_cases_upload table for the customer_site referenced in your WHERE clause. The LEFT JOIN is joining all 8 records to each row of the enviro_figures_upload table, regardless of the completion_date. Does the customer_cases_upload completion_date match the corresponding enviro_figures_upload completion_date? If so, include this in your LEFT JOIN's ON clause to only join the customer_cases_upload rows to enviro_figures_upload rows with the same completion_date.
Id MedId ShipId AvailableQuant DefaultQuant MinQuant MedExpiry LastUsed
------ ------ ------ -------------- ------------ -------- ------------------- ---------------------
1 1 2918 20 30 15 2015-02-05 11:37:24 2014-12-01 11:37:32
4 2 2918 50 55 30 2015-03-26 11:57:14 2014-12-03 11:57:22
5 3 2918 15 40 20 2014-12-10 16:58:58 2014-12-10 16:59:02
6 4 2918 30 75 30 2015-03-31 11:58:26 2014-12-03 11:58:32
7 5 2918 22 50 20 2015-01-01 11:59:05 2014-12-03 11:59:09
9 6 3095 5 35 10 2014-12-03 11:59:51 2014-09-01 11:59:55
10 7 2918 30 60 35 2014-12-01 12:00:43 2014-10-22 12:00:57
11 8 3095 25 30 20 2014-12-31 17:48:58 2014-12-01 17:49:12
And there are 2 queries that i have written
1)To give me count of critical Items
SELECT SUM(IF(m.AvailableQuant <= m.MinQuant,1, 0)) AS criticalFROM tbl_vesselmaster vs
INNER JOIN comp_login cl ON vs.co_id = cl.id
INNER JOIN m_shipinv m ON vs.id = m.ShipId
WHERE vs.co_id=$co_id;
2)To give me medicine that have excedeed expiry date
SELECT COUNT(MedId) as count FROM `m_shipinv` WHERE DATE(MedExpiry) < DATE(NOW());
i want a query to get the count intersection of this both query. means if the item is critical and its medicine is expired then it should count only 1
this should be the output
count
-------
4
I think you can just add the where clause to the first query:
SELECT SUM(m.AvailableQuant <= m.MinQuant) AS critical
FROM tbl_vesselmaster vs INNER JOIN
comp_login cl
ON vs.co_id = cl.id INNER JOIN
m_shipinv m
ON vs.id = m.ShipId
WHERE vs.co_id = $co_id OR DATE(MedExpiry) < DATE(NOW());
Note that I simplified the SUM() calculation. The if is not needed because MySQL treats booleans as integers in a numeric context.
Can't you just put the two conditions in the where clause ?
I don't understand all you inner joins as you only describe one table. I just altered the select of Gordon Linoff:
SELECT count(*) AS critical
FROM tbl_vesselmaster vs
INNER JOIN comp_login cl ON vs.co_id = cl.id
INNER JOIN m_shipinv m ON vs.id = m.ShipId
WHERE vs.co_id = $co_id
AND DATE(MedExpiry) < DATE(NOW())
AND m.availableQuant <= m.minQuant;
I think the result should be 3: only records 5, 9 and 10 meet both criteria.