Find out the report generation name - mysql

Currently I have three tables, namely: hospital, doctor and test. The report generation time is calculated using report time minus the sample test time. How can I write a query to find out which hospital has the least average report generation time?
Table name: hospital
|name|
| 'A' |
| 'B' |
| 'C' |
Table name: doctor
id
doctor_name
hospital_name
1
'Eric'
'A'
2
'Peter'
'A'
3
'Sam'
'B'
4
'Park'
'B'
5
'Alan'
'C'
6
'Andrew'
'C'
Table name: test
id
test_date
test_time
report_date
report_time
doctor_id
1
'2021-10-9'
'19:30:00'
'2021-10-9'
'23:30:00'
1
2
'2021-10-9'
'14:00:00'
'2021-10-9'
'22:20:00'
2
3
'2021-10-9'
'20:30:00'
'2021-10-10'
'08:00:00'
3
4
'2021-10-10'
'07:30:00'
'2021-10-10'
'13:10:00'
4
5
'2021-10-10'
'09:30:00'
'2021-10-10'
'13:30:00'
5
6
'2021-10-10'
'11:00:00'
'2021-10-10'
'22:00:00'
6
7
'2021-10-10'
'15:20:00'
'2021-10-10'
'19:00:00'
1
8
'2021-10-11'
'08:00:00'
'2021-10-11'
'20:00:00'
4
the column hospital_name in table 'doctor' references hospital.name and the column doctor_id in table 'test' references doctor.id
Expected result:
hospital_name
'A'
Explanation: From the 'test' table, we can get the average report generation time of Hospital 'A' is 320 minutes since there are three records about Hospital 'A' (the doctors whose id are 1 and 2) and the average report generation time of Hospital 'B' is 1630 / 3 minutes since there are three records about Hospital 'B' (the doctors whose id are 3 and 4) and the average report generation time of Hospital 'C' is 450 minutes since there are two records about Hospital 'C' (the doctors whose id are 5 and 6). As a result, the answer is Hospital 'A'.
select TIMESTAMPDIFF(minute, timestamp(test_date,test_time),
timestamp(report_date, report_time)) from test as t
inner join doctor as d
on t.doctor_id = d.id
inner join hospital as h
on d.hospital_name = h.name;
I don't know how to find the average generation time

select h.name as hospital_name, count(t.id) as total_tests, SUM(TIMESTAMPDIFF(minute, timestamp(test_date,test_time),
timestamp(report_date, report_time))) as total_time, (SUM(TIMESTAMPDIFF(minute, timestamp(test_date,test_time),
timestamp(report_date, report_time)))/count(t.id)) as avg_time from test as t
inner join doctor as d
on t.doctor_id = d.id
inner join hospital as h
on d.hospital_name = h.name group by h.id

After executing query, you can get these results, check them

Related

MYSQL : Get data from multiple table using JOIN and UNION in single row

I have three database tables ‘customer’, ‘billing’, and ‘transaction’
customer:
cuid
name
address
1
David
City 1
2
Roja
City 2
billing :
id
cuid
month
bill_amount
1
1
1
100
2
1
2
200
3
2
1
400
4
1
3
100
transaction:
id
cuid
date
received_amount
1
1
2022-3-02
250
2
2
2022-2-02
200
3
2
2022-3-02
200
I need a new generated Due table after calculating month wise due amount using FIFO like this:
cuid
Name
Address
Month
Due_Amount
1
David
City 1
2
50
1
David
City 1
3
100
This code did not work properly. MySql Code:
SELECT
due.cuid,
due.Name,
due.Address,
due.Month,
sum(due.Amount - due.Received) AS Due_Amount
FROM
(SELECT
c.cuid,
c.name AS name,
c.address AS address,
b.month AS Month,
0 AS Received,
b.bill_amount AS Amount
FROM
customer c
INNER JOIN billing b ON c.cuid=b.cuid
UNION ALL
SELECT
c.cuid,
c.name AS Name,
c.address AS Address,
null AS Month,
t.received_amount AS Received,
0 AS Amount
FROM
customer c
INNER JOIN transaction t ON c.cuid = t.cuid) AS due
GROUP BY
due.cuid;
Code generated table is :
cuid
Name
Address
Month
Due_Amount
1
David
City 1
1
150
2
Roja
City 2
1
0
You probably don't need all that SUM(), UNION ALL and subquery. You can do it in a single query and JOIN all three tables like this:
SELECT c.cuid,
c.Name,
c.Address,
b.Month,
t.received_amount-b.bill_amount AS Due_Amount
FROM customer c
JOIN billing b
ON c.cuid=b.cuid
JOIN transaction t
ON c.cuid=t.cuid
AND b.month=MONTH(t.date);
Demo fiddle
I do have a slight curiosity though because my understanding of Due_amount is the remaining amount need to be paid by the customer and yours doesn't seem to be one. If it is, then the value should be negative because the customer David paid more (received_amount) than the bill_amount.

SQL query to create a merged table with varied timestamps and varied column mapping

I am trying to write an complex mySQL query in which there are 2 tables action and revenue what I need is:
From auction table take out location, postal code on the basis of user, cat_id, cat and spent and join with revenue table which has revenue column so as that given cat_id, cat and date I can figure out the returns that each 'postal' is generating.
Complexities:
User is unique key here
In auction table has column 'spent' but its populates only when 'event' column has 'show' but it has 'cat' entry. And 'cat_id' starts populating at any event except show. So need to map cat_id from 'cat' for event 'show' to get the spent for that cat_id.
The date has to be setup such that while joining the tables the timestamp should be compared for plus minus 10 mins. Right now in my query I have 24 hrs duration
Aggregating on postal in desc order to postal giving highest returns
**Auction Table**
dt user cat_id cat location postal event spent
2020-11-01 22:12:25 1 0 A US X12 Show 2
2020-11-01 22:12:25 1 0 A US X12 Show 2 (duplicate also in table)
2020-11-01 22:12:25 1 6 A US X12 Mid null
2020-11-01 22:13:20 2 0 B UK L23 Show 2
2020-11-01 22:15:24 2 3 B UK L23 End null
**Revenue table**
dt user cat_id revenue
2020-11-01 22:14:45 1 6 null
2020-11-01 22:13:20 2 3 3
Want to create final table(by aggregating on revenue for each 'postal' area):
location postal spend revenue returns
UK X12 2 0 0
US L23 2 3 3/2=1.5
I have written a query but unable to figure out solution for above mention 3 complexities:
Select s.location, s.postal, s.spend, e.revenue
From revenue e JOIN
auction s
on e.user = s.user
where s.event in ('Mid','End','Show') and
TO_DATE(CAST(UNIX_TIMESTAMP(e.dt, 'y-M-d') AS TIMESTAMP)) = TO_DATE(CAST(UNIX_TIMESTAMP(s.dt, 'y-M-d') AS TIMESTAMP)) and
s.cat_id in ('3') and
s.cat = 'B'
Any suggestion will be helpful
This answers the question for MySQL, which is the original tag on the question as well as mentioned in the question.
If I understand correctly, your issue is "joining" within a time frame. You can do what you want using a correlated subquery. Then the rest is aggregation, which I think is:
select location, postal, max(spend), max(revenue)
from (select a.*,
(select sum(r.revenue)
from revenue r
where r.user = a.user and
r.dte >= s.dt - interval 10 minute and
r.dte <= s.dte + interval 10 minute
) as revenue
from auction a
where s.event in ('Mid', 'End', 'Show') and
s.cat_id in (3) and
s.cat = 'B'
) a
group by location, postal;

configure query to bring rows which have more than 1 entries

How to get those entries which have more than 1 records?
If it doesn't make sense... let me explain:
From the below table I want to access the sum of the commission of all rows where type is joining and "they have more than 1 entry with same downmem_id".
I have this query but it doesn't consider more entries scenario...
$search = "SELECT sum(commission) as income FROM `$database`.`$memcom` where type='joining'";
Here's the table:
id mem_id commission downmem_id type time
2 1 3250 2 joining 2019-09-22 13:24:40
3 45 500 2 egbvegr new time
4 32 20 2 vnsjkdv other time
5 23 2222 2 vfdvfvf some other time
6 43 42 3 joining time
7 32 353 5 joining time
8 54 35 5 vsdvsdd time
Here's the expected result: it should be the sum of the id no 2, 7 only
ie. 3250+353=whatever.
It shouldn't include id no 6 because it has only 1 row with the same downmem_id.
Please help me to make this query.
Another approach is two levels of aggregation:
select sum(t.commission) income
from (select sum(case when type = 'joining' then commission end) as commission
from t
group by downmem_id
having count(*) > 1
) t;
The main advantage to this approach is that this more readily supports more complex conditions on the other members of each group -- such as at most one "joining" record or both "joining" records and no more than two "vnsjkdv" records.
Use EXISTS:
select sum(t.commission) income
from tablename t
where t.type = 'joining'
and exists (
select 1 from tablename
where id <> t.id and downmem_id = t.downmem_id
)
See the demo.
Results:
| income |
| ----- |
| 3603 |
You can use subquery that will find all downmem_id having more than one occurrence in the table.
SELECT Sum(commission) AS income
FROM tablename
WHERE type = 'joining'
AND downmem_id IN (SELECT downmem_id
FROM tablename t
GROUP BY downmem_id
HAVING Count(id) > 1);
DEMO

MySQL query - Inner join using only the latest version of an entry

I have a table, named jobs with various pieces of information. Each job is given a job number (unique id).
There is then another table, named purchaseOrders that has a FK of jobID and a PK of poID.
when a purchase order entry is edited, the old information is saved... meaning, i create a new PO entry (new unique id).
What i'm trying to do, is write one query that selects all fields from "jobs" and all fields from "purchaseOrders" but only the latest poID for that job.
For example:
jobID Name State poID time jobID
========================== ==========================
1 foo fl 1 1:00 1
2 bar ga 2 1:10 1
3 zzz ny 3 1:20 1
4 2:00 2
5 2:01 2
6 2:30 2
7 3:00 3
8 3:40 3
9 3:15 3
How can I run a query that will select all the columns from both tables, but only include the information with the highest poID for the specific jobID?
SELECT a.*, c.*
FROM jobs a
INNER JOIN
(
SELECT jobID, MAX(time) maxVal
FROM purchaseOrders
GROUP BY jobID
) b ON a.jobID = b.jobID
INNER JOIN purchaseOrders c
ON c.jobID = b.JobID AND
c.time = b.maxVal
SQLFiddle Demo

MySQL date reservation

I try to find a similar question but didn't find an exact one so I'll post mine:
I have 2 tables:
room (room_id)
room_reservation (room_id, date)
How can I return list of rooms that have at least 1 day free between 2 dates.
For example, if I have those rooms:
room_id 1, 2 & 3
then in room_reservation table, I have the following:
1 - 2012-07-22
1 - 2012-07-23
1 - 2012-07-24
1 - 2012-07-25
1 - 2012-07-26
2 - 2012-07-23
2 - 2012-07-24
then doing a search for available room between 2012-07-22 and 2012-07-26 should return only room #2 and #3.
I have this query so far but didn't work... please help!
SELECT DISTINCT room_id AS id
FROM room
WHERE (SELECT COUNT('listing') FROM listing_calendar WHERE listing = l.listing_id AND date BETWEEN '2012-07-22' AND '2012-07-26' GROUP BY listing) < 5"
Thanks for the help!
You can use this solution:
SELECT a.room_id
FROM rooms a
LEFT JOIN room_reservations b ON
a.room_id = b.room_id AND
b.date BETWEEN '2012-07-22' AND '2012-07-26'
GROUP BY a.room_id
HAVING COUNT(b.room_id) < DATEDIFF('2012-07-26', '2012-07-22') + 1
SQLFiddle Demo