I have these three tables
Table #1: Ships IDs
Ship ID Ship Code
1 ALBE
2 AMBS
3 AMBR
Table #2 : Equipment Data
Ship ID Equipment_ID
1 1001
1 1002
1 1003
2 1004
2 1005
2 1006
3 1007
3 1008
3 1009
Table #3 : Counters
Equipment_ID Hours Date_Updated
1001 2 2018-01-01
1001 4 2018-05-01
1002 3 2018-01-01
1002 5 2018-05-01
1003 5 2018-01-01
1003 10 2018-05-01
1004 1 2018-01-01
1004 6 2018-05-01
1005 3 2018-03-01
1006 6 2018-03-01
1007 5 2018-01-01
1007 12 2018-05-01
1008 15 2018-01-01
1008 19 2018-05-01
1009 4 2018-01-01
1009 12 2018-06-01
I want the below result:
Per each Ship Code the last counter hours and equipment_id categorized as AE1,AE2,AE3 where AE1 are 1001,1004,1007 AE2 are 1002,1005,1008 and AE3 are 1003,1006,1009
Ship Code AE1 AE2 AE3
ALBE 4 5 10
AMBS 6 6 12
AMBR 12 19 12
How can I create this dynamic pivot table?
Use conditional aggregation:
select s.ship_code,
sum(case when e.equipment_id in (1001, 1004, 1007) then hours else 0 end) as ae1,
sum(case when e.equipment_id in (1001, 1004, 1007) then hours else 0 end) as ae2,
sum(case when e.equipment_id in (1003,1 006, 1009) then hours else 0 end) as ae3
from ships s left join
equipment e
on e.ship_id = s.ship_id left join
counters c
on c.equipment_id = e.equipment_id
group by s.ship_code;
You could approach the pivot table like so:
Ship Code Equipment ID Hour Type
ALBE 4 AE1
AMBS 6 AE1
AMBR 12 AE2
AMBR 12 AE3
That way you could query it more easily
Related
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
I have some values which is based on date for different groupings
For each grouping id, what is the max of value till a particular date.
Example
Date Grouping Id Value
2017-06-01 1 100
2017-06-03 1 101
2017-06-06 1 103
2017-06-02 2 200
2017-06-04 2 210
2017-06-08 2 220
2017-06-01 2 1000
2017-06-05 2 1020
2017-06-09 2 1050
I need the output like below
Date Grouping Id Value
2017-06-01 1 100
2017-06-02 1 100
2017-06-03 1 101
2017-06-04 1 101
2017-06-05 1 101
2017-06-06 1 103
2017-06-07 1 103
2017-06-08 1 103
2017-06-09 1 103
2017-06-10 1 103
2017-06-01 2 NULL
2017-06-02 2 200
2017-06-03 2 200
2017-06-04 2 210
2017-06-05 2 210
2017-06-06 2 210
2017-06-07 2 210
2017-06-08 2 220
2017-06-09 2 220
2017-06-10 2 220
2017-06-01 3 1000
2017-06-02 3 1000
2017-06-03 3 1000
2017-06-04 3 1000
2017-06-05 3 1020
2017-06-06 3 1020
2017-06-07 3 1020
2017-06-08 3 1020
2017-06-09 3 1050
2017-06-10 3 1050
So assuming you have the TEMPLATE_TABLE that has all days x all grouping IDs data, you can try below two queries:
CREATE TABLE TABLE_1 AS
SELECT A.DATE, A.GROUPING_ID, B.VALUE
FROM
TEMPLATE_TABLE A
LEFT JOIN
GIVEN_TABLE B
ON A.DATE = B.DATE AND A.GROUPING_ID = B.GROUPING_ID
ORDER BY A.GROUPING_ID, A.DATE;
Above table TABLE_1 will pad values for matches and NULL for non-matches.
You can use this table to find maximum values till a given date for all dates through a self join given in the below query:
SELECT B.DATE, B.GROUPING_ID, MAX(A.VALUE) AS VALUE
FROM
TABLE_1 A
INNER JOIN
TABLE_1 B
ON A.GROUPING_ID = B.GROUPING_ID AND A.DATE<=B.DATE
GROUP BY B.DATE, B.GROUPING_ID;
Hope this works. Let me know if this doesn't.
I have a table
date d_id r_id p_id q_sold onhand
2012-10-10 5 1 3025 3 10
2012-10-10 5 1 3022 12 20
2012-10-10 5 1 3023 15 33
2012-10-11 5 1 3025 3 10
2012-10-11 5 1 3022 12 20
2012-10-11 5 1 3023 15 33
2012-10-12 5 1 3025 3 10
2012-10-12 5 1 3022 12 20
2012-10-12 5 1 3023 15 33
2012-10-13 5 1 3025 3 10
2012-10-13 5 1 3022 12 20
2012-10-13 5 1 3023 15 33
2012-10-14 5 1 3025 3 10
2012-10-14 5 1 3022 12 10
2012-10-14 5 1 3023 15 33
2012-10-15 5 1 3025 3 5
2012-10-15 5 1 3022 12 5
2012-10-15 5 1 3023 15 33
I would like to get the result of the q_sold divided by average of the onhand over a 5 day period, while displaying the other data for a specific date like the 2012-10-15.
I create a query
set #stdate = '2012-10-10';
set #endate = '2012-10-15';
SELECT date, d_id,r_id,p_id,q_sold,onhand,qty_sold/AVG(qty_onhand)
FROM stp_vwsales_info_tots
WHERE date BETWEEN #stdate and #endate and d_id=5
GROUP BY d_id,r_id,p_id
But the result being showed is incorrect, it displays the data for the 2012-10-10 instead of 2010-10-15
date d_id r_id p_id q_sold onhand avg
2012-10-10 5 1 3022 12 20 0.7579
2012-10-10 5 1 3023 15 33 0.4545
2012-10-10 5 1 3025 3 10 0.3273
Can anyone help?
Use your #stdate and #endate as DATE(#stdate/#endate) or DATE_FORMAT(#stdate/#endate,'%Y-%m-%d') otherwise you have to convert #stdate/#endate from string to date through MySQL
i think what your looking for is something called a simple moving average.
to calculate this you'll need to use an inline subquery - so performance won't be the best.
assuming you want to calculate the average over the previous 5 day period, try something like this:
SELECT
date, d_id, r_id, p_id, q_sold, onhand,
( SELECT q_sold/AVG(t2.onhand)
FROM stp_vwsales_info_tots AS t2
WHERE p_id=t1.p_id AND DATEDIFF(t1.date, t2.date) BETWEEN 0 AND 4
) AS 'moving_avg'
FROM stp_vwsales_info_tots AS t1
GROUP BY t1.p_id,t1.date
order by t1.date;
tab1
id code name
1001 0 palani
1002 1001 shanker
1003 1002 raghu
1004 1003 kabhir
1005 1003 vani
1006 1002 priya
tab2
id code name amount tax
1 1002 b 100 1
2 1002 j 20 10
3 1003 jk 23 20
4 1004 jk 675 9
5 1005 o 67 3
6 1003 u 122 4
7 1003 o 98 1
8 1003 iu 98 1
9 1002 po 4 0.4
10 1005 pl 1 0.1
12 1005 tf 1 0.1
24 1006 e 23 2.3
id 1001 see code 1001 corresponding id 1002
id 1002 see code 1002 corresponding id 1003,1006
id 1003 see code 1003 corresponding id 1004,1005
others no need
Result need like this
code amount tax
1001 124 11.4
1002 364 28.3
1003 744 12.2
Please send the mysql query for this
GROUP BY is your friend:
select tab1.id, sum (tab2.amount) amount, sum (tab2.tax) tax
from
tab1, tab2
where tab1.code = tab2.id
and tab1.id in (1001, 1002, 1003)
group by tab1.id
This will get what you want from tab2
SELECT code, SUM(amount), SUM(tax) FROM tab GROUP BY code ORDER BY code
I can't see how tab1 fits into what you want
does it work (not tested)
select SUM(t2.amount) AS Amount,SUM(t2.tax) AS totalTax,t2.code FROM
table2 t2
INNER JOIN table1 t1 ON t1.code=t2.code
ap table
id tid code pid cl date
1 1 1002 17 DC 2011-04-05 16:14:37
2 1 1002 18 DC 2011-04-05 16:14:37
3 1 1002 19 DC 2011-04-05 16:14:37
4 2 1002 12 SC 2011-04-05 16:15:59
5 2 1002 9 SC 2011-04-05 16:15:59
6 2 1002 21 SC 2011-04-05 16:15:59
7 3 1003 20 DC 2011-04-07 14:57:40
8 3 1003 12 DC 2011-04-07 14:57:40
9 3 1003 9 DC 2011-04-07 14:57:40
10 3 1003 21 DC 2011-04-07 14:57:40
11 4 1002 18 SC 2011-04-08 18:10:04
12 4 1002 19 SC 2011-04-08 18:10:04
13 4 1002 22 SC 2011-04-08 18:10:04
14 5 1001 17 SC 2011-04-08 18:21:10
at table
tid totalamount code pstatus cdate
1 65.98 1002 R 2011-04-05 16:14:37
2 17.74 1002 R 2011-04-05 16:15:59
3 96.36 1003 R 2011-04-07 14:57:40
4 25.94 1002 S 2011-04-08 18:10:04
5 9 1001 R 2011-05-08 18:21:10
i tried like this but its not correct
SELECT at.totalamount, at.pstatus, ap.cl
FROM `at` AS at
INNER JOIN ap AS ap ON at.`code` = ap.`code`
WHERE ap.cl = 'SC'
AND at.`code` = '1002'
GROUP BY at.`code`
LIMIT 0 , 30
I expected Result
pstatus->S pstatus->R
code Stotalamount Rtotalamount Sstatus Rstatus cl
1002 25.94 17.74 S R SC
Please any body tell me the correct query
It seems you want to add the totalamount twice, once for the the R status and another for the S status.
But I don't understand how you are joining the ap table and why the 65.98 is not added. Should the join be done on the date columns as well?
This may work but you have to test it with different data to be sure. Or explain more of what the columns in the two tables represent and what you want the query to show.
SELECT at.code
, SUM(IF(at.pstatus='S', at.totalamount, 0))
AS Stotalamount
, SUM(IF(at.pstatus='R', at.totalamount, 0))
AS Rtotalamount
FROM at
WHERE EXISTS
( SELECT 1
FROM ap
WHERE at.code = ap.code
AND at.cdate = ap.date
AND ap.cl = 'SC'
)
AND at.code = 1002
GROUP BY at.code
LIMIT 0 , 30