I've two tables as below:
1. tbl_student:
id name
1 raj
2 raja
3 raju
4 rajan
tbl_attendance
id student_id month attended_days
1 1 1 6
2 1 2 16
3 8 1 8
4 7 2 14
5 8 2 13
6 7 1 11
I need to join these two tables combining multiple rows for each month for each student from tbl_attendance into a single row to obtain a result like this:
id name month attended_days month attended_days
1 raj 1 6 2 16
7 raja 1 11 2 14
8 rajan 1 8 2 13
Thanks in advance for any help.
Instead of displaying month value in each of the records,
you can use them as column headers and attendance as their value.
Use pivot type solution to achieve required solution.
Example:
select s.id as student_id
, s.name as student_name
, max( case when a.month = 1 then a.attended_days else null end ) as month_1
, max( case when a.month = 2 then a.attended_days else null end ) as month_2
, max( case when a.month = 3 then a.attended_days else null end ) as month_3
-- ...
, max( case when a.month = 12 then a.attended_days else null end ) as month_12
from table_student s
left join table_attendance a on s.id = a.student_id
group by s.id, s.name
Your question is not very complete, but i think you want something like this:
select s.*,
coalesce(a1.month, a2.month, a3.month) as month,
coalesce(a1.attended_days , a2.attended_days , a3.attended_days ) as attended_days
from table_student s
left join table_attendance a1 on s.id = a1.student_id and a1.month = 1
left join table_attendance a2 on s.id = a2.student_id and a2.month = 2
left join table_attendance a3 on s.id = a3.student_id and a3.month = 3
The previous code is used if you want to show all months in one column. For multiple columns, you can use this example:
select s.*,
a1.month as month_1,
a2.month as month_2,
a3.month as month_3,
a1.attended_days as attended_days_1,
a2.attended_days as attended_days_2,
a3.attended_days as attended_days_3
from table_student s
left join table_attendance a1 on s.id = a1.student_id and a1.month = 1
left join table_attendance a2 on s.id = a2.student_id and a2.month = 2
left join table_attendance a3 on s.id = a3.student_id and a3.month = 3
Do this for all the 12 months. I used 3 as example.
Related
I have a table that looks like this:
id name yearofstudy mark
1 Alain A 2 75
2 Michael B 3 85
3 Chen C 1 55
4 Caroline D 2 60
5 Mohamed E 2 60
6 Alex F 1 55
7 Sofia O 3 78
8 Samir O 1 85
9 Rob G 2 78
10 Big K 3 55
And I'm trying to get the id, name, year and mark of the students with the lowest (and highest) mark in each year which would give:
id name yearofstudy mark
3 Chen C 1 55
4 Caroline D 2 60
10 Big K 3 55
SQL isn't my strong point and I've been trying using the MIN() function but I haven't managed to get it right yet and would really appreciate some help.
Using a subquery to get the min() and max() for each yearofstudy, and joining it to the original table. (You did say you wanted lowest and highest, right?)
select t.id, t.name, t.yearofstudy, t.mark
from t
inner join (
select
yearofstudy
, min(mark) as minMark
, max(mar) as maxMark
from t
group by yearofstudy
) as m
on t.yearofstudy = m.yearofstudy
and (t.mark = minMark or t.mark = maxMark)
or for just the lowest mark per year:
select t.id, t.name, t.yearofstudy, t.mark
from t
inner join (
select
yearofstudy
, min(mark) as minMark
from t
group by yearofstudy
) as m
on t.yearofstudy = m.yearofstudy
and t.mark = minMark
You could write the query as follows:
SELECT t1.* from your_table t1
INNER JOIN (
SELECT yearofstudy, MIN(marks) as marks
FROM your_table GROUP BY yearofstudy
) t2
ON t1.yearofstudy = t2.yearofstudy
AND t1.marks = t2.marks
GROUP BY t1.yearofstudy
ORDER BY t1.yearofstudy, t1.id;
If all the MIN records for the yearofstudy are required, then you could simply remove GROUP BY t1.yearofstudy
Demo
I am looking to generate the results into the horizontal union. I could able to combine together and generate the results. However, I need to show the results in the expected results format.
SQL
(SELECT
kpa_id AS 'KPA', SUM(weightage) AS 'Total'
FROM
pmm_question_details
WHERE
weightage NOT LIKE '%-%'
GROUP BY kpa_id) UNION (SELECT
kpa_id AS 'KPA', SUM(weightage_value) AS 'Acheived'
FROM
pmm_answer_details
WHERE
application_id = 2
AND archive_value = 'No'
GROUP BY kpa_id)
Actual Results
1 14
2 37
3 19
4 40
5 51
6 24
1 12
2 19
3 0
6 2
Expected Results
1 14 1 12
2 37 2 19
3 19 3 0
4 40 6 2
5 51
6 24
If we can assume pmm_question_Details will always have as many or more records than pmm_answer_details... then two subqueries and a left join should do the trick with a join on a uservariable rownum (RN)
SELECT A.KPA, A.Total, B.KPA, B.Acheived
FROM (SELECT kpa_id AS 'KPA'
, SUM(weightage) AS 'Total'
, #RN1 := #RN1 + 1 as RN
FROM pmm_question_details
CROSS JOIN (SELECT #RN1 :=0) r1
WHERE weightage NOT LIKE '%-%'
ORDER BY KPA
GROUP BY kpa_id) A
LEFT JOIN (SELECT kpa_id AS 'KPA'
, SUM(weightage_value) AS 'Acheived'
, #RN1 := #RN2 + 1 as RN
FROM pmm_answer_details
CROSS JOIN (SELECT #RN2 :=0) r2
WHERE application_id = 2
AND archive_value = 'No'
ORDER BY KPA
GROUP BY kpa_id) B
on A.RN = B.RN
ORDER BY A.KPA
Though I must admit I don't see why a rownumber is needed if you could just left join on the KPA_ID in the first place...
if this could be the Expected results... (and again assuming pmm_question has all the IDs which could be in pmm_answer... )
Expected Results
1 14 1 12
2 37 2 19
3 19 3 0
4 40
5 51
6 24 6 2
Then the query would just be...
SELECT A.KPA, A.Total, B.KPA, B.Acheived
FROM (SELECT kpa_id AS 'KPA', SUM(weightage) AS 'Total'
FROM pmm_question_details
WHERE weightage NOT LIKE '%-%'
GROUP BY kpa_id) A
LEFT JOIN (SELECT kpa_id AS 'KPA', SUM(weightage_value) AS 'Acheived'
FROM pmm_answer_details
WHERE application_id = 2
AND archive_value = 'No'
GROUP BY kpa_id) B
on A.KPA = B.KPA
SELECT mf.fm_id,ema.asc_code as 'Xaxis', count(*) as 'Total'
from els_jobsheet_data as jd
join master_asc as ma on (jd.asc_id=ma.asc_id )
join els_master_asc_l3l4 as ema on jd.els_asc_code =ema.asc_code
join master_city as mc on mc.city_id=ma.city_id
join master_state as ms on ms.state_id=mc.state_id
join master_region as mr on mr.region_id=ms.region_id
join master_fso as mf on mf.fm_id=mr.fso_id
where jd.insert_time is not null AND jd.insert_time>='2015-12-01'
AND jd.insert_time<='2015-12-31'
group by Xaxis
order by Xaxis ASC
A query returned-
fm_id Xaxis Total
2 DOA 43
3 DSRO 12
1 TRC 12
9 3423 10
5 5455 11
2 2443 13
7 55AS 2
But I want to group it like
fm_id Xaxis Total
2 DOA 43
3 DSRO 12
1 TRC 12
9 Other 342
(whatever be its total)
i m newbie.Pls help..
Use a case expression instead of the raw data.
SELECT
max(mf.fm_id) as fm_id
, CASE
WHEN ema.asc_code IN ('DOA', 'DSRO', 'TRC') THEN ema.asc_code
ELSE 'Other'
END AS Xaxis
, COUNT(*) AS Total
FROM els_jobsheet_data AS jd
JOIN master_asc AS ma ON (jd.asc_id = ma.asc_id)
JOIN els_master_asc_l3l4 AS ema ON jd.els_asc_code = ema.asc_code
JOIN master_city AS mc ON mc.city_id = ma.city_id
JOIN master_state AS ms ON ms.state_id = mc.state_id
JOIN master_region AS mr ON mr.region_id = ms.region_id
JOIN master_fso AS mf ON mf.fm_id = mr.fso_id
WHERE jd.insert_time IS NOT NULL
AND jd.insert_time >= '2015-12-01'
AND jd.insert_time <= '2015-12-31'
GROUP BY
CASE
WHEN ema.asc_code IN ('DOA', 'DSRO', 'TRC') THEN ema.asc_code
ELSE 'Other'
END
ORDER BY
Xaxis ASC
My table is similar to the one below. I would like to select records where city and town matches and code or area has repetition. In this case rows the result should be all rows except the ones with id 3 and 5. Thanks for looking at this
city town id code1 code2 code3 code4 area1 area2 area3 area4
----------------------------------------------------------------------------------
dublin town1 1 1 2 3 5 1 2 3 4
dublin town1 2 2 8 10 6 7 8 9
dublin town1 3 12 13 15 11 12 13 14
dublin town2 4 1 2 3 5 1 2 3 4
dublin town2 5 6 7 8 10 6 7 8 9
dublin town2 6 11 12 13 15 1 12 13 14
http://sqlfiddle.com/#!2/0bbe7/1/0
Using INNER JOIN,
select a.*
from bigcities a inner join bigcities b
on a.city = b.city
and a.town = b.town
and a.id != b.id
and (a.code1 = b.code1
or a.code2 = b.code2
or a.code3 = b.code3
or a.code4 = b.code4
or a.area1 = b.area1
or a.area2 = b.area2
or a.area3 = b.area3
or a.area4 = b.area4
);
Demo.
This is pretty much what the exists clause can do. Here is a solution for your conditions:
select t.*
from <table> t
where exists (select 1
from <table> t2
where t2.city = t.city and
t2.town = t.town and
t2.id <> t.id and
(t2.code1 = t.code1 or t2.code2 = t.code2 or t2.code3 = t.code3 or t2.code4 = t.code4 or
t2.area1 = t.area1 or t2.area2 = t.area2 or t2.area3 = t.area3 or t2.area4 = t.area4
)
You can do it with the following query
--We do a query to the table to get the rows and then we do a subquery
--to get all the rows with the same criteria. We know it is repeated
--because the counter of rows > 1.
--If you want to get only where it is repeated 2 o 3, etc, you only need to change
--the COUNT() > 1
SELECT *
FROM tableName t
WHERE (
SELECT COUNT(*) FROM tableName tRep WHERE
t.city = tRep.city AND
t.town = tRep.town AND
((t.code1 = tRep.code1 AND t.code2 = tRep.code2 AND t.code3 = tRep.code3 AND t.code4 = tRep.code4) OR
(t.area1 = tRep.area1 AND t.area2 = tRep.area2 AND t.area3 = tRep.area3 AND t.area4 = tRep.area4))
) > 1
--work--
day hours
4 8
5 9
6 8
--crew--
employee day
2 4
3 4
6 4
2 5
3 5
4 5
--break--
hours day employee
1 4 2
.5 5 3
Here is the sql query i have:
SELECT w.hours, w.hours-b.hours, c.employee
FROM work w
LEFT JOIN crew c ON w.day = c.day
LEFT JOIN break b ON w.day = b.day
WHERE w.day = 4
this is subtracting 1 hour from every employee
i want the break.hours to be subtracted only if that employee has taken a break.
if he hasn't, i simply want work.hours.
COALESCE is all you need.
SELECT a.employee,
a.day,
b.hours - COALESCE(c.hours,0) totalHours
FROM crew a
INNER JOIN work b
ON a.day = b.day
LEFT JOIN `break` c
ON a.employee = c.employee AND
a.day = c.day
-- WHERE b.day = 4
SQLFiddle Demo Link
SQLFiddle Demo Link (with WHERE clause)