I have a mysql db with three tables
student
student_intervention
intervention details
I'm trying to do a pivot table view that shows all the students and has columns for each intervention type totalling up the different types of intervention for each student.
So far I have
SELECT t.`first_name`, t.`last_name`, t.`student_id`,
Count(IF(t.`intervention_details_id` = 1, 1, null)) AS Intervention1,
Count(IF(t.`intervention_details_id` = 0, 1, null)) AS Intervention2
FROM (
SELECT student.`student_id`, student.`first_name`,
student.`last_name`,
`student_intervention`.`intervention_details_id`
FROM student, student_intervention
WHERE student_intervention.student_id = student.`student_id`
) t
GROUP BY t.student_id
This works but it only shows data for students who have an intervention. I want a full list of students including those without an intervention. I think I need a JOIN but cannot figure out the right one.
Can anyone help?
use LEFT JOIN instead
SELECT a.`student_id`,
a.`first_name`,
a.`last_name`,
SUM(IF(COALESCE(b.`intervention_details_id`,0) = 1, 1, 0)) Intervention1,
SUM(IF(COALESCE(b.`intervention_details_id`,0) = 0, 1, 0)) Intervention2
FROM student a
LEFT JOIN student_intervention b
ON b.student_id = a.`student_id`
GROUP BY a.`student_id`, a.`first_name`, a.`last_name`
if you want prepared statement
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN COALESCE(b.intervention_details_id ,0) = ',
COALESCE(b.intervention_details_id ,0),
' THEN 1 ELSE 0 END) AS ',
COALESCE(b.intervention_details_id ,0)
)
) INTO #sql
FROM student a
LEFT JOIN student_intervention b
ON b.student_id = a.student_id;
SET #sql = CONCAT('SELECT a.student_id , a.first_name , a.last_name , ', #sql, '
FROM student a
LEFT JOIN student_intervention b
ON b.student_id = a.student_id
GROUP BY a.student_id , a.first_name , a.last_name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Related
I have a dynamic MySQL query and I want to create a table based on the dynamic MySQL pivot table. I am using Laravel, and I have the query in a blade file instead of a controller. Below is the query.
How can I create a dynamic table, with dynamic headers (instead of static) ?
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(assessements.id = ''',
assessements.id,
''', marks.mark, NULL)) AS ',
replace(assessement_name, ' ', '')
)
) INTO #sql
from assessements INNER JOIN marks ON marks.assessement_id=assessements.id WHERE assessements.term_id=2;
SET #sql = CONCAT('SELECT student_subject_averages.student_average,
student_subject_averages.ca_average,
student_subject_averages.exam_mark,
subjects.subject_name,
subjects.subject_type,
subjects.id as subject_id,
users.name,
users.salutation,
users.lastname, ', #sql, ' from marks
INNER JOIN assessements ON assessements.id = marks.assessement_id
INNER JOIN teaching_loads ON teaching_loads.id = marks.teaching_load_id
INNER JOIN subjects ON subjects.id = teaching_loads.subject_id
INNER JOIN users ON users.id = marks.teacher_id
INNER JOIN student_subject_averages ON student_subject_averages.student_id = marks.student_id
WHERE marks.student_id = 1869 AND `assessements`.`term_id` = 2 AND marks.active=1 AND student_subject_averages.teaching_load_id=marks.teaching_load_id
GROUP BY
marks.student_id,student_subject_averages.student_id,
subjects.id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I am getting above result from this query
SELECT sa.Student_Id,
CONCAT_WS(' ', es.Student_FName, es.Student_LName) AS Full_Name,
sa.Attendance_Date ,
sa.Attendance_Status
FROM student_attendance sa
INNER JOIN courses c
ON c.Course_Id = sa.Course_Id
INNER JOIN campus ca
ON ca.Campus_Id = c.Campus_Id
INNER JOIN students es
ON es.Student_Id = sa.Student_Id
WHERE sa.Course_Id = 1
ORDER BY sa.Attendance_Date DESC;
but i want this result
Can someone Do this for me Please..
select max(student|_id),full_name as student_FName ,
case attendance_date when attendance_date ='03-02-2016' and attendance_status =0
and full_name ='Shehriar Khan'
Then 'p' end as '3/1/2016',
case attendance_status when attendance_date ='03-01-2016'
and attendance_status =0 and full_name ='Ahtesham Illahi'
Then 'p' end as '3/2/2016'
from table_name
group_by full_name,attendance_date,attendance_stauts
Try like this
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(a.attendance_status = ''',
attendance_status,
''', IF(a.attendance_status = "1","P","X"), NULL)) AS "',
attendance_date,'"'
)
) INTO #sql
FROM student_attendance;
SET #sql = CONCAT('SELECT a.Student_ID,a.student_name,', #sql, '
FROM student_attendance a
LEFT JOIN student_attendance AS b
ON a.Student_ID=b.Student_ID GROUP BY a.Student_ID,b.Student_ID');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Fiddle link
I have bellow query but has problem
set #lang = "en";
SELECT
COUNT(*) AS total_of_user,
COUNT(*) AS "total_of_user_#lang",
src.district AS district_name,
src.district AS "district_name_#lang"
FROM users LEFT JOIN (
SELECT
d.district_code,
d.name_en AS district,
p.name_en AS province_name,
p.`province_code`
FROM
provinces AS p LEFT JOIN districts AS d ON p.province_code = d.province_code
WHERE
p.province_code = '01'
) AS src ON src.district_code = users.district_code
WHERE
users.district_code IS NOT NULL AND
users.district_code <> '' AND
users.province_code = '01'
GROUP BY users.district_code
If I remove " from query the never run, but above query run and result came as district_name_#lang but I need the column name to be as district_name_en.
For any help thanks.
You would need to use dynamic SQL for this:
set #lang = 'en';
set #sql = '
SELECT COUNT(*) AS total_of_user,
COUNT(*) AS total_of_user_#lang,
src.district AS district_name,
src.district AS district_name_#lang
FROM users LEFT JOIN
(SELECT d.district_code, d.name_en AS district, p.name_en AS province_name, p.`province_code`
FROM provinces p LEFT JOIN
districts d
ON p.province_code = d.province_code
WHERE p.province_code = ''01''
) src
ON src.district_code = users.district_code
WHERE users.district_code IS NOT NULL AND
users.district_code <> '''' AND
users.province_code = ''01''
GROUP BY users.district_code';
set #sql = replace(#sql, '#en', #en);
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
Note: you cannot use parameters for column names or table names in a dynamic query.
I need to create a SQL query that lists the following tables. Lines from the language list as column names. Thanks
Picture table and query:
If languages are known upfront
SELECT r.id, r.parent,
MAX(CASE WHEN n.language_id = 1 THEN n.name END) cs,
MAX(CASE WHEN n.language_id = 2 THEN n.name END) en
FROM cat_route r LEFT JOIN cat_route_name n
ON r.id = n.cat_route_id
GROUP BY r.id
Here is SQLFiddle demo
If you want it to be dynamic depending on what languages you defined in language
SET #sql = NULL;
SELECT GROUP_CONCAT(CONCAT(
'MAX(CASE WHEN n.language_id = ', id, ' THEN n.name END) `', short, '`'))
INTO #sql
FROM language;
SET #sql = CONCAT(
'SELECT r.id, r.parent, ', #sql, '
FROM cat_route r LEFT JOIN cat_route_name n
ON r.id = n.cat_route_id
GROUP BY r.id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Here is SQLFiddle demo
I have a problem ordering my stored procedure by a parameter given by a user, I have tried reading but the solutions I have tried won't work.
So, is there somebody who can help me? I would like it to be sorted by Type from my Group_concat. It works if I type it in harcoded, like (ORDER BY Type1, ORDER BY Type2 and so on). But I would like something like this (ORDER BY #specificStat).
CREATE PROCEDURE getSpecificStatsBySeason(IN khID INT(11), IN seasonName varchar(40), IN specificStat INT(11))
BEGIN
SET #sql = NULL;
SET #khID = khID;
SET #seasonName = seasonName;
SET #specificStat = specificStat;
SELECT
GROUP_CONCAT(DISTINCT CONCAT('SUM(IF(em.eventTypeID = ',
et.eventTypeID, ', 1, 0)) AS Type',
et.eventTypeID )
) INTO #sql
FROM eventTypes AS et, `eventType-R-kh` AS eRk, kh AS kh WHERE et.eventTypeID = eRk.eventTypeID AND eRk.kh = kh.kh AND kh.khID = #khID;
SET #sql = CONCAT('SELECT u.userID, ud.firstname, ud.lastname,', #sql,
',
IFNULL((SELECT COUNT(s.activityID)
FROM activity AS a1, signup AS s
WHERE u.userid = s.userid
AND s.activityID = a1.activityID
AND a1.khID = #khID
AND s.answer = 1
AND se.seasonName = #seasonName
AND a1.activityDate BETWEEN se.seasonStart AND se.seasonEnd
AND a1.activityDate <= NOW()), 0) AS matchCount
FROM userData AS ud, userInfo AS u
LEFT JOIN activity AS a ON a.khID = #khID
RIGHT JOIN season AS se ON se.seasonName = #seasonName
AND a.activityDate BETWEEN se.seasonStart AND se.seasonEnd
LEFT JOIN `eventMatch` AS em ON em.userid = u.userid
AND em.activityID = a.activityID
LEFT JOIN activityMatch AS am ON a.activityID = am.activityID
WHERE u.khID = #khID
AND u.userID = ud.userID
GROUP BY u.UserID
ORDER BY #specificStat ;');
prepare stmt
FROM #sql;
execute stmt;
Use this instead:
...
...
AND u.userID = ud.userID
GROUP BY u.UserID
ORDER BY ', #specificStat, ' ;');