subquery in group_concat with IN clause - mysql

tbl_a
id dept_id
1 1,2,3
2 2,3
3 1
tbl_b
dept_id dept
1 a
2 b
3 c
My query:
SELECT id, (SELECT GROUP_CONCAT(dept) FROM tbl_b
WHERE tbl_b.dept_id IN (tbl_a.dept_id)) as departments
FROM tbl_a
This only returns the first value of the tbl_a.dept_id.
I want to have a result as.
id departments
1 a,b,c
2 b,c
3 a

First of all if its possible to change the structure then normalize it,use junction table which stores id of table a and ids from table b with a one-to-many relation,if you can't change schema you can use find_in_set
select a.id,group_concat(b.`dept` order by b.`dept`) departments
from a
join b on(find_in_set(b.dept_id,a.dept_id) > 0)
group by a.id
Demo

Related

Merge two tables with same columns and get the column value in specific table

I have two tables that have the same column of position and salary.
Table_a
ID
Name
Position
Salary
1
Peter
Sale
10,000
2
Tom
IT
15,000
3
Jane
Sale
12,000
4
Mary
PR
8,000
5
John
IT
14,000
Table_b
ID
Position
Salary
1
Driver
9,000
2
Manager
20,000
4
Sale
13,000
I would like to merge two tables that the output is based on the Position value and Salary value of Table_b.
Output
ID
Name
Position
Salary
1
Peter
Driver
9,000
2
Tom
Manager
20,000
3
Jane
Sale
12,000
4
Mary
Sale
13,000
5
John
IT
14,000
Please give me an advice how can I query and get the above output.
SELECT id,
t1.name,
COALESCE(t2.position, t1.position),
COALESCE(t2.salary, t1.salary)
FROM table_a t1
LEFT JOIN table_b t2 USING (id)
Some rows in table_a don't have a matching row in table_b. Any rows in table_b that don't have a matching row in table_a will be ignored. We assume that ID is unique in each table (meaning for example there won't be two rows in table_b with the same ID value). We will match the rows on ID value.
We can make table_a the driving table in an outer join to table_b. Let's first get that working, returning all the columns from both tables, and verify the return is what we expect.
SELECT a.ID
, a.Name
, a.Position
, a.Salary
, b.ID AS b_ID
, b.Position AS b_position
, b.Salary AS b_salary
FROM table_a a
LEFT
JOIN table_b b
ON b.ID = a.ID
ORDER
BY a.ID
We see that in the result from the first query, on rows where we didn't get a matching row from table_b, column b_ID (and all the columns from table_b) are NULL.
We can add some expressions in the SELECT list to get the Salary from table_b where we found a matching row, or otherwise return Salary from table_a where we didn't.
There's lots of possible expressions to do that, but they all key on the idea that when we don't have a matching row from the outer joined table, the values in those columns will be NULL.
So the trick is test whether we found a matching row from table_b (or if we did get a matching row in table_b, the row had a NULL value for Salary)
Adding some example expressions to check if b.ID or b.Salary is NULL.
SELECT a.Name
, a.Position
, a.Salary
, b.ID AS b_ID
, b.Position AS b_position
, b.Salary AS b_salary
, CASE WHEN b.ID IS NULL THEN a.Salary ELSE b.Salary END AS _Salary_x1
, IFNULL(b.Salary,a.Salary) AS _Salary_x2
, IF(b.Salary IS NULL,a.Salary,b.Salary) AS _Salary_x3
FROM table_a a
LEFT
JOIN table_b b
ON b.ID = a.ID
ORDER
BY a.ID

Counting and grouping columns with multiple JOIN's

I have 3 tables:
Table A
----------------------------
id | data
----------------------------
1 nothing important
2 nothing important
3 nothing important
Table B
-----------------------------------------
id | table_a_id | table_c_id
-----------------------------------------
1 1 1
2 1 2
3 1 3
Table C
----------------------------
id | name
----------------------------
1 Bob Saget
2 Neil deGrasse Tyson
3 Mike Tyson
Table B and C are 1:1 relationship, whereas Table A and Table B are a one to many relationship.
I want to get a count of the JOINed rows in Table B.
Here is my attempt that does not work:
SELECT count(*) AS count, tC.name FROM table_a tA
LEFT JOIN table_b tB ON tA.id = tB.table_a_id
LEFT JOIN table_c tC ON tC.id = tB.table_c_id
GROUP BY tA.id, tC.name
This is what I'm hoping the result will look like:
Result
----------------------------
count | name
----------------------------
3 Bob Saget
3 Neil deGrasse Tyson
3 Mike Tyson
Count represents the number of rows that were JOINed from Table B. In this case, 3 rows from table B carry a foreign key for table A.
Use can use this fiddle.
If you want to count how many rows in a relate to each c, then c has to come first in the from clause, followed by left joins to the other tables.
Also, you need to a.id from the group by clause - otherwise, you would probably get just one (or zero) row per group.
Other things to consider:
you are left joining, so you should count something from a rather than just count(*), so you get 0 for unmatched rows (instead of 1 with count(*))
I would recommend grouping by the primary key of c rather than on the name, in case two different ids might have the same name
So:
SELECT count(a.id) AS count, c.name
FROM table_c c
LEFT JOIN table_b b ON c.id = b.table_c_id
LEFT JOIN table_a a ON a.id = b.table_a_id
GROUP BY c.id

sql - select rows with a distinct value in a specific column

Let's assume that I have the following table:
id player_name team
1 Gladiator A
2 DarkLord B
3 Alligator A
4 MonaLisa C
5 SpongBob C
6 Mikasa B
I want to select one player from each team, which means that all the selected rows must have a unique value in the 'team' column. How can I accomplish this in MySQL?
In my example the selected rows should be:
id player_name team
1 Gladiator A
2 DarkLord B
4 MonaLisa C
This is one way to do it using a derived table so you select one id per team and join it to the original table.
select t.id, t.player_name, t.team
from tablename t
join (select team, min(id) as minid from tablename group by team) x
on x.team = t.team and x.minid = t.id
One simple way would be to fetch using a group by criteria. (Assuming your table name is TEAM_TABLE)
SELECT * FROM TEAM_TABLE GROUP BY TEAM;
This would return the first record occurring for each value of the team column.

Select Multi rows from table B according to array value in table A

I have two tables (A, B), B table has a column Fruit which stores id values of table A rows as array, how can I output IN ONE SELECT STATEMENT the title of each id in table B, like that:
Table B :
id title
1 Apple
2 Orange
Table A :
id Fruit
1 1,2
result:
A.id A.Fruit
1 Apple,Orange
SELECT a.id, GROUP_CONCAT(b.title)
FROm tableA a
LEFT JOIN tableB b
ON FIND_IN_SET(b.id , a.Fruit)
GROUP BY a.id
SELECT Fruit FROM Table B WHERE Fruit IN (SELECT Fruit FROM Table A); I don't know if this will work for you but I hope it helps. You will probably need to use Subqueries.

How to get two tables data using single mysql query?

Following is my tables which is student id is common field in both tables. I want to get both tables data in single query.Also get recent data of student.
table A:
student_id name surname email
------------------------------------------------
1 ABC LLL abc#gmail.com
2 PQR SSS pqr#gmail.com
Table B:
student_id Assignment_Id Assignment_Name last_submited
---------------------------------------------------------------------
2 1 asign_1 sub_0001
1 2 asign_2 sub_0002
2 3 asign_2 sub_0003
I want exact output like:-
student_id Assignment_Id email last_submited
--------------------------------------------------------------
2 3 pqr#gmail.com sub_0003
I have used following query for getting recent record but confused how to get email id along with this.
SELECT assignment_id,
student_id,
last_submited
FROM tableB
WHERE student_id= '2'
ORDER BY assignment_id DESC LIMIT 1
You can make use of a JOIN
select tableB.assignment_id,
tableB.student_id,
tableB.last_submited,
tableA.email
from tableB INNER JOIN
tableA ON tableB.student_id = tableA.student_id
where tableB.student_id= '2'
order by tableB.assignment_id desc
limit 1
INNER JOINs are used to return data where the data is in both tables (so en entry would exist in tableA and tableB).
LEFT JOINs are used when you wish to retrieve all data from tableA and those values that are available in tableB.
So, lets say you had
TABLEA
-------
1
2
and
TABLEB
-------
1
SELECT *
FROM TABLEA INNER JOIN
TABLEB ON TABLEA.ID = TABLEB.ID
would return
1,1
Whereas
SELECT *
FROM TABLEA LEFT JOIN
TABLEB ON TABLEA.ID = TABLEB.ID
would return
1,1
2,NULL
You need to use join
SELECT a.student_id,
b.Assignment_id,
a.email,
b.last_submitted
FROM a
INNER JOIN b ON a.student_id = b.student_id
WHERE a.student_id= '2'
ORDER BY b.assignment_id DESC LIMIT 1
Join both the tables,
SELECT B.assignment_id,
B.student_id,
A.email_id ,
B.last_submited
FROM tableB 'B',
tableA 'A'
WHERE B.student_id= '2'
AND A.student_id=B.student_id
ORDER BY assignment_id DESC LIMIT 1