Counting and grouping columns with multiple JOIN's - mysql

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

Related

How to perform LEFT OUTER JOIN in hive without duplicates to check only one value in the right table?

I have two datasets:
1)
Table A
id name
1 raju
2 ramu
2 ramu
3 rakesh
Table A
2)
Table B
id Status
1 Y
1 Y
2 N
2 N
2 Y
3 N
Table B
I want to perform a left outer join (Table A Left outer join Table B) in hive in such a way that while joining the two datasets on column 'id', if the Status column in table B has 'Y' at least once, then the resultant dataset will have the Status as 'Yes' like below:
Final Result:
id name Status
1 raju Yes
2 ramu Yes
2 ramu Yes
3 rakesh No
I do not want to increase the number of records in the result while performing the join. The result table should have only 4 records, not 5(increased
records based on the matching join condition).
How do I achieve this?
To meet this requirement, you need to reduce the row count of your table B to either one row or zero rows per row of table A.
Do that like this, getting one row for every id value with a status of Y.
SELECT DISTINCT id, Status
FROM B
WHERE Status = 'Y'
Then you can use the old LEFT JOIN ... IS NOT NULL trick to figure out which rows of A have matching rows of B.
This does it. (http://sqlfiddle.com/#!9/71d84b/1/0)
SELECT A.id, A.name,
CASE WHEN B.Status IS NOT NULL THEN 'Yes' ELSE 'No' END Status
FROM A
LEFT JOIN (
SELECT DISTINCT id, Status
FROM B
WHERE Status = 'Y'
) B ON A.id = B.id

How to get ONLY common rows of 2 tables on MySQL?

Probably is something simple, but, let's say I have these:
Table User (id_user, name)
Table A (id_a, name, type, #id_user)
And then I have another one that have only its own id and the other foreign keys
Table B (id_b, #id_user1, #id_user2, #id_a, #id_Something)
So, I need a query that returns ONLY the rows of table A and table B with what they have in common. I've tried INNER JOIN but it returns all rows of Table A where the id_user from there is equal to the id_user from table B. Like, if I have these:
Table User:
id_user name
1 Hey
Table A:
id_a name type id_user
1 a car 1
2 b cat 1
Table B:
id_b id_user id_user2 id_a id_Something
1 1 Doesn't matter 1 Doesn't matter
I need to return only the common row between Table A and Table B (that'll be something like:
id_a name type id_user id_b id_user2
1 a car 1 1
I've tried INNER JOIN but it returns to me everything when the id_user from A = id_user from B. I used this syntax:
SELECT *
FROM B
INNER JOIN A ON A.id_user = B.id_user;
Hope I've made myself clear, thank you a lot.
Is what you're going after: "Show me all the rows in A and B which share the same id_user"
SELECT User.id_user, User.name, a.id_a, b.id_b
FROM User
INNER JOIN A ON a.id_user = User.id_user
INNER JOIN B on b.id_user = User.id_user

Conditional select statement using 3 tables

I am trying to do a conditional case statement and am not sure if sql can perform this.
I need to select the ID from Table A, and the Name from the corresponding ID in table B. If the Name in Table B is NULL, i need to select the Name from Table C. I am not sure how to do this using a CASE or if it is possible, any help is greatly appriciated.
Table A Table B Table C
ID ID2 ID2 Name ID2 Name
________ ___________ ___________
1 3 1 bill 1 NULL
2 2 2 steve 2 NULL
3 1 3 NULL 3 george
Use IFNULL() to select the appropriate column from B or C.
SELECT a.id, IFNULL(b.name, c.name) AS name
FROM a
JOIN b ON a.id = b.id2
JOIN c ON a.id = c.id2
If the matching rows could be missing from B or C, use LEFT JOIN instead of JOIN.
Try the following query:
select IFNULL(TableB.name, TableC.name) as name
from TableA
left join TableB TableA.ID2=TableB.ID2
left join TableC TableA.ID2=TableC.ID2
I was too slow :p
Here is a fiddle, if it might help someone: http://sqlfiddle.com/#!9/b28c5/2
I assumed that each ID2 value is present in either both or none of TableB/TableC.

subquery in group_concat with IN clause

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

How to get row info from two tables based on the column value of first table

I have the following two tables:
TableA
article_id | attribute_id
1 | 5
2 | 6
TableB
attribute_id | attribute_name
5 | foo
6 | bar
How would I get the corresponding row if I only know the article id? So if I pass article_id 1 I get:
article_id | attribute_id | attribute_name
1 | 5 | foo
I know I could do it with two separate queries but was wondering if it could be done in one? I thought about using INNER JOIN ON but article_id isn't in both tables?
Thanks
For sure, you can (and have to) use INNER JOIN.
SELECT TableA.article_id, TableB.*
FROM TableA
INNER JOIN TableB ON TableA.attribute_id = TableB.attribute_id
WHERE TableA.article_id = 1
The SELECT part let us retrieve article_id from the first table, and all fields from the second one.
The INNSER JOIN clause joins rows that have the same attribute_id from the two tables.
The WHERE condition let us select only the row with article_id = 1 in first table.
Use NATURAL JOIN - Wikipedia Entry
SELECT *
FROM TableA NATURAL JOIN TableB
WHERE article_id = 1
select article_id, tablea.attribute_id,attribute_name
from tablea,tableb where
tablea.attribute_id=tableb.attribute_id
and article_id= :passedId
Join using attribute_id
SELECT * FROM TableA A, TableB B where
A.attribute_id = B.attribute_id