How to group by a column with forloop and union all - php

Hi this is my query from this query i am getting 3 records i want only one record and i am trying to group by studentid
foreach ($gdFinaldata['gdskill'] as $skillId => $skillScore){
$filterQuery .= $union_all. "SELECT stu.student_pid
FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email
LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid
WHERE job_id = ".$jobID." AND skill_id = ".$skillId." AND gd_score >= ".$skillScore." ";
$union_all=" UNION ALL ";
} //for ends here
the recodrs will come like this:
SELECT stu.student_pid FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid WHERE job_id = 88 AND skill_id = 3 AND gd_score >= 1
UNION ALL
SELECT stu.student_pid FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid WHERE job_id = 88 AND skill_id = 63 AND gd_score >= 2
UNION ALL
SELECT stu.student_pid FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid WHERE job_id = 88 AND skill_id = 128 AND gd_score >= 3
After this i want to add group by how can i do that i tried like this:
$groupby = "GROUP BY student_id";
$filterStudents = $conn->query($filterQuery.$groupby);
My issue is still returning 3 records i want to group by student
For Reference:

There are several ways to do this.
Use union instead of union all, this will retain only unique entries
select ...
union
select ...
union
select ...
If you want to keep union all (why do you?), use parenthesis around your selects and append group by after it
select student_pid
( select student_pid, student_id from ...
union all
select student_pid, student_id from ...
union all
select student_pid, student_id from ... ) as t
group by student_id
Your PHP would then look like
foreach (...) {
$filterQuery .= $union_all. "SELECT stu.student_pid, jsc.student_id ..."
// ...
}
$outerQuery = "select student_pid ("
$groupby = ") as t GROUP BY student_id";
$filterStudents = $conn->query($outerQuery . $filterQuery . $groupby);
Instead of group by, you can also use distinct, e.g.
select distinct student_pid
( select student_pid from ...
union all
select student_pid from ...
union all
select student_pid from ... ) as t
Collect the result in an array and then use array_unique
Although this is the least efficient, since it fetches all entries instead of the relevant parts.

Related

How to give CASE WHEN THEN in mysql where clause based on select columns?

I am using select query and selection columns in which i have to get total count of a column as well as condition based count
for total count column name in select query is ims_total_count (condition is_correct IN (1,0))
for column name ims_code_count condition is_correct = 0
i paste my code below
SELECT q.ims_code,
COUNT(q.ims_code) AS ims_total_count,
M.NAME,
M.score_board_order,
M.id AS exam_id,
M.view_question_hr ,
M.section_id,
GROUP_CONCAT(DISTINCT M.section_id) AS coded_section,
GROUP_CONCAT(DISTINCT REPLACE(SUBSTRING_INDEX(M.NAME,'Sec', 1) ,'New ','') ) AS coded_test_name,
COUNT(q.ims_code) AS ims_code_count,
q.question_password,
qcat.NAME AS topic_name,
qsubcat.NAME AS cat_name,
qsubcat.description AS sub_cat_name,
GROUP_CONCAT( DISTINCT UPPER( REPLACE(LOWER(q.question_code),'new','') ) ) AS coded_que,
GROUP_CONCAT( DISTINCT q.id ) AS coded_que_id,
GROUP_CONCAT(q.exam_id) AS coded_exam_id
FROM y2a_watupro_question AS q INNER JOIN y2a_watupro_master AS M
ON q.exam_id = M.id LEFT JOIN y2a_watupro_qcats AS qcat
ON q.cat_id = qcat.id LEFT JOIN y2a_watupro_qsub_cats AS qsubcat
ON q.sub_cat_id = qsubcat.id
WHERE q.id IN (
SELECT question_id
FROM y2a_watupro_student_answers
WHERE CASE is_correct WHEN ims_total_count THEN '1,0'
ELSE '0' END AND taking_id IN (
SELECT t.id
FROM y2a_watupro_taken_exams AS t INNER JOIN y2a_test_score_board_section AS s
ON s.id = t.section_id
WHERE s.sc_id =0
AND t.user_id=5270
AND t.trial_status = 1
AND t.in_progress = 0
AND t.isactive = 1 )
)
GROUP BY M.score_board_order, q.ims_code
ORDER BY M.score_board_order ASC;
SELECT *,CASE
WHEN OCCUPATION = 'I am Salaried' THEN 'Salaried'
WHEN OCCUPATION = 'I am not Employed' THEN 'Student'
WHEN OCCUPATION = 'I am Retired' THEN 'Retired'
WHEN OCCUPATION = 'I am Self Employed' THEN 'Self Employed'
WHEN OCCUPATION = 'I Run Business' THEN 'Own Business'
WHEN OCCUPATION = 'I am a Professional (Dr/CA/LLB/Engg etc)' THEN 'Professional'
ELSE 'OCCUPATION'
END AS OCCUPATION FROM TABLE_NAME;
This is works fine for me.

How to select few values with and condition?

I have table example http://prntscr.com/msqpep
I need empty result when i am doing
SELECT * FROM prods
WHERE prod_id = 3 and (fet_id = 1 and fet_id = 5)
but that code so not work (fet_id = 1 and fet_id = 5) or (fet_id = 1 and fet_id = 3)
"Where in" is a best way but i need `WHERE IN(1 and 2 and 3)
By default "WHERE IN" working as (1 or 2 or 3)
When I select fet_id=1 and fet_id=3 i need two results
When i select fet_id=1 and fet_id=5 i need no result
You probably want
SELECT prod_id FROM prods GROUP by prod_id
HAVING (SUM(fet_id=1)>0
AND SUM(fet_id=5)>0)
OR
(SUM(fet_id=1)>0
AND SUM(fet_id=3)>0)
HAVING filters groups WHERE filters rows.
Try This:
SELECT p1.id AS id1, p2.id AS id2
FROM `prods` p1 LEFT JOIN `prods` p2 ON p1.`prod_id` = p2.`prod_id`
WHERE p1.`fet_id` = '1' AND p2.`fet_id` = '3'
Output
id1 id2
1 3
With input fet_id=1 & fet_id=5
SELECT p1.id AS id1, p2.id AS id2
FROM `prods` p1 LEFT JOIN `prods` p2 ON p1.`prod_id` = p2.`prod_id`
WHERE p1.`fet_id` = '1' AND p2.`fet_id` = '5'
Output: No result
And another one if need more then two values
SELECT res.* FROM (SELECT 3 as total,
(SELECT COUNT(*) FROM `prods` as t1 WHERE t1.`fet_id` = 1 OR t1.`fet_id` = 2 OR t1.`fet_id` = 5) as current,
t2.*
FROM `prods` as t2 WHERE t2.`fet_id` in (1,2,5)) as res WHERE res.total = res.current

Print out a union select

I have the following query:
$query = mysql_query(" ( SELECT naam
FROM users_social
WHERE user_id = 1 )
UNION
( SELECT COUNT(DISTINCT DATE(datetime)) as days
FROM users_social_invoer
WHERE user_id = 1 )"
);
Now I can echo the first part of the query (the 'naam') with the following echo:
echo mysql_fetch_row($row_query[0]);
However echo'ing $row_query[1] does NOT print out the 2nd part of the query (the union select) as I would like to. How do I actually print out that part of the query? thanks
You need JOIN instead of UNION
SELECT us.naam, count(DISTINCT DATE(usi.datetime)) as days
FROM users_social as us
JOIN users_social_invoer as usi
ON us.user_id = usi.user_id
WHERE us.user_id = 1
GROUP BY us.naam

I cant figure out how to write an sql query to display the information how I want

I've gotten my database set up for my website and I'm a little baffled on how I should write the SQL query to display the information how I want it.
Here's an image of how my database is setup and an example of how I want to display it:
Here's the SQL query I wrote to get the information (Im open to writing a better solution)
SELECT * FROM drinks_category, drinks_lookup, drinks
WHERE drinks.drink_id = drinks_lookup.drink_id
AND drinks_lookup.drinks_category_id = drinks_category.drinks_category_id
This gets me all the info but I'm not sure how to write the output to get it to show how i want.
One solution is to order by category:
SELECT *
FROM drinks_category, drinks_lookup, drinks
WHERE drinks.drink_id = drinks_lookup.drink_id
AND drinks_lookup.drinks_category_id = drinks_category.drinks_category_id
ORDER BY drinks_category.drink_category_title
With that, you can loop in PHP, and output a new header whenever a new category appears. Something like this:
<?php
$last_category = 0;
foreach($data as $row) {
if($row['drinks_category_id'] != $last_category) {
echo '<h1>' . $row['drink_category_title'] . '</h1>';
}
echo '<div>' . $row['drinks_name'] . '</div>';
$last_category = $row['drinks_category_id'];
}
?>
You should probably use nested html lists instead of the markup above, but this should get you started.
Since you use PHP, the best way to do this is to use an outer-inner-query loop:
Outer query: SELECT * FROM drings_category, then loop:
Display drink_category_title
Use drink_category_id as $ID for SELECT drinks.drink_name FROM drinks INNER JOIN drinks_lookup ON drinks.drink_id=drinks_lookup.drink_id WHERE drinks_lookup.drink_category_id=$ID
Loop and display drinks
Hideously over complicated way to do it in a single sql statement for 3 fixed columns, coping with up to 1000 drinks in each category.
SELECT DrinkCategory1Subselect.drink_name AS 'Drink Category Title', DrinkCategory2Subselect.drink_name AS 'Drink Category Title 2', DrinkCategory3Subselect.drink_name AS 'Drink Category Title 3'
FROM (SELECT a.i+b.i*10+c.1*100 AS aCounter
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) b,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) c) Deriv1
INNER JOIN (SELECT c.drink_name,
#Counter := #Counter + 1 AS aCounter
FROM drinks_category a
INNER JOIN drinks_lookup b ON a.drink_category_id = b.drink_category_id
INNER JOIN drinks c ON b.drink_id = c.drink_id
CROSS JOIN (SELECT #Counter:=0) NothingUseful
WHERE a.drink_category_id = 1
ORDER BY c.drink_id) DrinkCategory1Subselect
ON DrinkCategory1Subselect.aCounter = Deriv1.aCounter
INNER JOIN (SELECT c.drink_name,
#Counter := #Counter + 1 AS aCounter
FROM drinks_category a
INNER JOIN drinks_lookup b ON a.drink_category_id = b.drink_category_id
INNER JOIN drinks c ON b.drink_id = c.drink_id
CROSS JOIN (SELECT #Counter:=0) NothingUseful
WHERE a.drink_category_id = 2
ORDER BY c.drink_id) DrinkCategory2Subselect
ON DrinkCategory2Subselect.aCounter = Deriv1.aCounter
INNER JOIN (SELECT c.drink_name,
#Counter := #Counter + 1 AS aCounter
FROM drinks_category a
INNER JOIN drinks_lookup b ON a.drink_category_id = b.drink_category_id
INNER JOIN drinks c ON b.drink_id = c.drink_id
CROSS JOIN (SELECT #Counter:=0) NothingUseful
WHERE a.drink_category_id = 3
ORDER BY c.drink_id) DrinkCategory3Subselect
ON DrinkCategory3Subselect.aCounter = Deriv1.aCounter
WHERE DrinkCategory1Subselect.drink_name IS NOT NULL
OR DrinkCategory2Subselect.drink_name IS NOT NULL
OR DrinkCategory3Subselect.drink_name IS NOT NULL
ORDER BY Deriv1.aCounter
Not tested. Better to do the formatting in php, but was bored

How can I build this query to compare a id with two tables?

I have drawn this image to explain what I need
1.to compare a user_id with the user_id's in two different tables
2.the corresponding ref_global_id from both the tables are then matched to a events table
3.matching global_id's from the events table are then arranged in ascending order.
Or this:
SELECT e.global_id, e.event_time
FROM (SELECT * FROM table1
UNION
SELECT * FROM table2) x inner join
event_table e ON e.global_id = x.ref_global_id
WHERE x.[user_id] = 121
SELECT e.global_id, e.event_time
FROM events_table e
JOIN table1 t1 on e.global_id = t1.ref_global_id
JOIN table2 t2 on e.global_id = t2.ref_global_id
WHERE t1.user_id = 121 AND t2.user_id = 121
ORDER BY e.event_time
Try this:
select global_id, event_time from event left join table1 on event.global_id = table1.ref_global_id AND table1.user_id = 121 left join table2 on event.global_id = table2.ref_global_id AND table2.user_id = 121

Categories