MySQL LEFT JOIN dates with order - mysql

I have a following tables:
sensors:
id name key code
1 s1 abc 123
2 s2 def 456
3 s3 ghi 789
measurements:
id value sensor_id generated_at
1 1.0 1 2013-12-30 06:00:00
2 1.0 1 2013-12-30 06:01:00
3 1.0 1 2013-12-30 06:02:00
4 3.0 2 2013-12-30 07:00:00
5 3.0 2 2013-12-30 07:01:00
6 3.0 2 2013-12-30 07:05:00
7 5.0 3 2013-12-30 08:02:00
8 5.0 3 2013-12-30 08:03:00
9 5.0 3 2013-12-30 08:11:00
10 5.0 3 2013-12-30 08:15:00
What I want to do is to generate report with all sensors data and include first and last generated_at time for received measurements, so the result of MySQL request should look like:
id name key code first_value_generated_at last_value_generated_at
1 s1 abc 123 2013-12-30 06:00:00 2013-12-30 06:02:00
2 s2 def 456 2013-12-30 07:00:00 2013-12-30 07:05:00
3 s3 ghi 789 2013-12-30 08:02:00 2013-12-30 08:15:00
I would appreciate any help, thanks.

I don't think that LEFT JOIN is really necessary here (only in case when there more or less sensors.id than in measurements.sensor_id). SQL query is below :
SELECT
s.id,
s.name,
s.key,
s.code,
m.first_value_generated_at,
m.last_value_generated_at
FROM sensors s JOIN
(SELECT
sensor_id,
MIN(generated_at) as first_value_generated_at,
MAX(generated_at) as last_value_generated_at
FROM
measurements
GROUP BY
sensor_id
) m ON s.id = m.sensor_id
ORDER BY
s.id

I hope this should work for you,
select *
,(select min(generated_at) from measurements as a where a.sensor_id =s.id) as first_value_generated_at
,(select max(generated_at) from measurements as b where b.sensor_id =s.id) as last_value_generated_at
from sensors as s

Try this query , it will generate the exact output you need
select s.id,s.name,s.key,s.code,min(m.generated_at) first_vaue_generated_at,max(m.generated_at) last_value_generated_at
from sensors s
LEFT JOIN measurements m ON (s.id = m.sensor_id)
group by 1,2,3,4;

Try this it will work
select s.id,s.name,s.key,s.code,m.generated_at as first_value_generated_at,ml.generated_at as last_value_generated_at from sensors as s,measurements as mf,measurements as ml where s.id = mf.sessor_id and s.id = ml.sensor_id and mf.generated_at < ml.generated_at group by mf.sensor_id

Maybe this could do that - nested selects?
select sensors.id, sensors.name, sensors.key, sensors.code,
( select generated_at from measurements order by time asc limit 1 )
as first_value_generated_at,
( select generated_at from measurements order by time desc limit 1 )
as last_value_generated_at from sensors

Related

how to generate student attendance percentage per course, when they have specific day in a week

hi guys i really newbie in sql, i need help to generate percentage of attendance, here is the table:
Table Schedule
Schedule_ID Course_ID Lecture_ID Start_Date End_Date Course_Days
1 1 11 2019-09-09 2019-12-08 2,4,6
2 3 4 2019-09-09 2019-12-08 3,4
3 4 13 2019-09-09 2019-12-08 2,5
4 5 28 2019-09-09 2019-12-08 3
5 2 56 2020-01-27 2020-04-26 2,4
6 7 1 2020-01-27 2020-04-26 4,5
7 1 11 2020-01-27 2020-04-26 2,4,6
8 7 22 2020-01-27 2020-04-26 2,3
9 8 56 2020-01-27 2020-04-26 5
10 3 37 2020-01-27 2020-04-26 5,6
Reference of days of week used in this data.
1: Sunday, 2:Monday, 3:Tuesday, 4:Wednesday, 5:Thursday, 6:Friday, 7:Saturday
Table course_attendance
ID STUDENT_ID SCHEDULE_ID ATTEND_DT
1 1 2 2019-09-10
2 1 2 2019-09-11
3 1 2 2019-09-17
4 1 2 2019-09-18
......
46 2 1 2019-12-02
47 2 1 2019-09-11
48 2 1 2019-09-18
49 2 1 2019-09-25
50 2 1 2019-10-09
51 2 1 2019-10-16
....
111 6 1 2019-09-23
112 6 1 2019-09-30
113 6 1 2019-10-07
114 6 1 2019-10-14
table student
ID NAME
1 Jonny
2 Cecilia
3 Frank
4 Jones
5 Don
6 Harry
i need to show up like this :
STUDENT_ID NAME Course_ID Attendance rate
1 Jonny 1 82%
2 Cecilia 1 30%
3 Frank 3 100%
4 Jones 2 100%
5 Don 2 25%
6 Harry 4 40%
EDIT this my last step to get percentage:
result:
with main as (
select ca.STUDENT_ID,
ca.SCHEDULE_ID,
s.COURSE_ID,
co.NAME as course_name,
st.NAME,
count(ca.ID) as total_attendance,
((CHAR_LENGTH(s.COURSE_DAYS) - CHAR_LENGTH(REPLACE(s.COURSE_DAYS , ',', '')) + 1) * 13) as attendance_needed
from univ.course_attendance ca
left join univ.schedule s on ca.SCHEDULE_ID = s.ID
left join univ.student st on ca.SCHEDULE_ID = st.ID
left join univ.course co on ca.SCHEDULE_ID = co.ID
group by ca.STUDENT_ID, ca.SCHEDULE_ID
)
select *,total_attendance/attendance_needed as attendance_percentage
from main
order by 1,2;
This can be done following three steps.
Step 1: Calculate the total number of days a particular course of a schedule has. It's a good thing the start_date is always on Monday and the end_date is always on Sunday, which makes the week complete and saves some trouble. By calculating the total number of weeks a course go through and the number of days a week has for that course, we can get the total number of days a particular course of a schedule has.
Step 2:Calculate the total number of days a student for a schedule. This is done fairly easily. Note: As the majority part of the table has been skipped and the OP has yet to provide the complete data set, I could only have 14 existing rows provided.
Step 3: Calculate the percentage for the attendance using the result from the above two steps and get other required columns.
Here is the complete statement I wrote and tested in workbench:
select t2.student_id as student_id,`name`,course_id, (t2.total_attendance/t1.total_course_days)*100 as attendance_rate
from (select schedule_id,course_id,
length(replace(course_days,',',''))*(week(end_date)-week(start_date)) as total_course_days
from Schedule) t1
JOIN
(select count(attend_dt) as total_attendance,student_id,schedule_id
from course_attendance group by student_id, schedule_id) t2
ON t1.schedule_id=t2.schedule_id
JOIN
student s
ON t2.student_id=s.id;
Here is the result set ( the attendance_rate is not nice due to the abridged course_attendance table):
student_id, name, course_id, attendance_rate
2, Cecilia, 1, 15.3846
6, Harry, 1, 10.2564
1, Jonny, 3, 15.3846

How to count max value in one month from 2 table

I have 2 table on my transaction
Table One
id | date | cust_id | driver_number
1 2019-01-02 1 F 3350 NN
2 2019-04-02 2 AX 111 Z
3 2019-05-02 3 S 787 X
4 2019-05-02 4 T 9090 M
5 2019-06-02 3 P 8989 L
Table Two
driver_number | price
F 3350 NN 350000
AX 111 Z 400000
S 787 X 375000
T 9090 M 900000
P 8989 L 500000
How do I count total transaction from two tables above in one month as per requested .
In example, request for total transaction in May so the result is like below
period | total
May 1275000
Thank you
Using MONTH(T1.date) = 5 and SUM(price) the expected result is achievable
SELECT MONTH(T1.date) AS Period, SUM(price) AS `Total`
FROM TableOne T1
JOIN TableTwo T2 ON T2.driver_number = T1.driver_number
WHERE MONTH(T1.date) = 5
GROUP BY MONTH(T1.date)

Get intersection of 2 tables in MySQL

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.

Select the 2 latest records from table

I have data like in this mysql table:
id customer_id date price
1 A 2014-01-01 4
2 A 2014-02-01 3
3 B 2014-03-01 2.5
4 B 2014-04-01 1
5 B 2014-05-01 5
6 C 2014-06-01 2
7 D 2014-07-01 2
8 D 2014-08-01 2.5
9 D 2014-09-01 1
I want to get the latest two dates for customer_id A, B and D. My result should be like this:
id customer_id date price
1 A 2014-01-01 4
2 A 2014-02-01 3
4 B 2014-04-01 1
5 B 2014-05-01 5
8 D 2014-08-01 2.5
9 D 2014-09-01 1
Any help is greatly appreciated.
One possible way :
SELECT *
FROM test s
WHERE (
SELECT COUNT(*)
FROM test f
WHERE f.customer_id = s.customer_id AND
f.`date` >= s.`date`
) <= 2
AND customer_id in('A','B','D');
[SQL Fiddle demo]
Try like this
select * from table where customer_id in('A','B','D') order by date desc limit 2

How to use Group By and Having together

I have following data set
id name units release_date
1 salil 1 2012-04-02
2 salil 2 2012-03-21
3 salil 3 2012-04-02
4 salil 4 2012-03-02
5 salil 5 2012-04-02
6 xyz 1 2012-04-01
7 xyz 2 2012-03-30
8 xyz 3 2012-03-30
9 xyz 4 2012-04-01
I want the SUM of an unit for Maximum date for each name. something like follwing
name units Max(release_date)
salil 9 2012-04-02
xyz 5 2012-04-01
I try following but it is not working
SELECT name, MAX(release_date) as date, sum(units) as units FROM reports
GROUP BY name;
Try below :
SELECT name, sum(units) as units
FROM reports as r
LEFT JOIN (select max(date) as maxdate from reports group by name ) as mr
ON r.date=mr.maxdate
WHERE artist_name='Pacer1' GROUP BY name;