SQL left JOIN with 4 columns - mysql

i have two tables
IDartist name
----------- -----------
1 akon
2 50 cent
IDsong name IDartist IDauthor IDcomposer IDmusicProducer
------ ---- -------- -------- --------- ---------------
1 lonley 1 2 1 2
how i out the name of whice IDartist,IDauthor,IDcomposer,IDmusicProducer ?
i tried to do this and its not working:
SELECT
songs.`IDsong`,
songs.`IDartist`,
songs.`name`,
songs.`IDgenre`,
songs.`IDauthor`,
songs.`IDcomposer`,
songs.`IDmusicProducer`,
artists.`name` As artists_name,
songs_genres.`name` As genres_name
FROM `songs`
LEFT OUTER JOIN `artists` ON (songs.`IDartist` = artists.`IDartist` OR songs.`IDauthor` = artists.`IDartist` OR songs.`IDcomposer` = artists.`IDartist` OR songs.`IDmusicProducer` = artists.`IDartist`)
LEFT OUTER JOIN `songs_genres` ON (songs.`IDgenre` = songs_genres.`IDgenre`)
WHERE songs.`IDsong`=XXX

In order to get the names of the artist, author, composer, and producer, you will have to join the artists table to the songs table for separate times. The query should look something like the following:
SELECT
s.IDsong, s.name,
a1.name AS artists_name,
a2.name AS author_name,
a3.name AS composer_name,
a4.name AS producer_name,
sg.name AS genres_name
FROM songs AS s
JOIN artists AS a1 ON s.IDartist = a1.IDartist
JOIN artists AS a2 ON s.IDauthor = a2.IDartist
JOIN artists AS a3 ON s.IDcomposer = a3.IDartist
JOIN artists AS a4 ON s.IDmusicProducer = a4.IDartist
JOIN songs_genres AS sg ON s.IDgenre = sg.IDgenre
If there may not be an artist, author, composer, and producer for a record then you will have to use LEFT JOIN on the tables instead.

Related

self join with inner join on other tables together

I have a database with 3 tables records, categories, relational.
records (id, lat, lng)
categories (c_id, c_value)
relational (r_id, c_id)
records
id | lat | lng
----------------------
1 23.57258 -35.28412
2 23.54855 -35.18881
3 23.74128 -35.17469
categories
c_id | c_value
---------------
100 groceries
101 bags
102 drinks
relational
id | c_id
------------
1 100
1 102
2 101
3 100
The relational.r_id = records.id and the relational.c_id = categories.c_id
I want to take pairs from records with different c_value, so I want to make a self join in records and inner join in categories and relational.
I've made this without the self join in records
SELECT id, lat, lng, c_value
FROM records
JOIN relational
ON records.id = relational.id
JOIN categories
ON relational.c_id = categories.c_id
WHERE c_value = "V1"
I tried something like this but it didn't work. I have problem with the R1.c_value.
SELECT R1._id, R1.lat, R1.lng, R1.c_value, R2._id, R2.lat, R2.lng,
R2.c_value
FROM records R1, records R2
JOIN relational
ON records.id = relational.id
JOIN categories
ON relational.c_id = categories.c_id
WHERE R1.c_value = "groceries" AND R2.c_value = "bags"
Do you know how can I combine those 3 joins in order to take 2 rows from records with the criteria of the other tables?
I want to have an output like this:
For "groceries" and "bags" as c.value
1 | 23.57258 | -35.28412 | groceries | 2 | 23.54855 | -35.18881 | bags
You can self join records table along with categories and relational like this:
SELECT r1.id, r1.lat, r1.lng, r2.id, r2.lat, r2.lng, c.c_value
FROM records r1 JOIN relational rl ON r1.id = rl.r_id
JOIN records r2 ON r2.id = rl.r_id
JOIN categories c ON rl.c_id = c.c_id
WHERE r1.id <> r2.id;
I finally found exactly what I wanted. My query should be like this. Thanks for the help and the idea anyway.
SELECT r1.id, r1.lat, r1.lng, c1.c_value, r2.id, r2.lat, r2.lng, c2.c_value
FROM records r1 JOIN relational rl1 ON rl1.id = r1.id
JOIN categories c1 ON rl1.c_id = c1.c_id
JOIN records r2 JOIN relational rl2 ON rl2.id = r2.id
JOIN categories c2 ON rl2.c_id = c2.c_id
WHERE c1.c_value = "groceries" AND c2.c_value = "bags"

How to find exact match item with AND condition from left outer join

I have a MySQL table
Booktable
+--------+-------------+-----+
| bookno | bookname | ... |
+--------+-------------+-----+
| 1 | FINALFANTASY| ... |
+--------+-------------+-----+
Authortable
+--------+-------------+-----+
| bookno | Authorname | ... |
+--------+-------------+-----+
| 1 | SQUARE | ... |
+--------+-------------+-----+
| 1 | ENIX | ... |
+--------+-------------+-----+
so I would like to make a search condition to get the book that match with the result.
I try with
select b.bookname,a.authorname from booktable as b
left outer join authortable a on b.bookno = a.bookno
where a.authorname = "square" and a.authorname = "enix"
It only work with only one where condition.but when I try with two authorname there is no result found. what should I do ?
(this query it working with "OR" but not "AND" but I really want the value that match the search condition or if there are some search condition that not match but not blank it should not be showing(so or it not working in this case)
Use aggregation to identify which books have both the authors you want:
SELECT t1.bookname,
t2.authorname
FROM booktable t1
INNER JOIN authortable t2
ON t1.bookno = t2.bookno
INNER JOIN
(
SELECT bookno
FROM authortable
WHERE authorname IN ('square', 'enix')
GROUP BY bookno
HAVING COUNT(DISTINCT authorname) = 2
) t3
ON t1.bookno = t3.bookno
Demo here:
SQLFiddle
Tim Biegeleisen's answer is great, but in case you need exactly match, the the last SQL in the following is correct:
SELECT * FROM book;
SELECT * FROM author;
/* this SQL will return book's author name more than 2 also true */
SELECT b.bookname, a.authorname
FROM book AS b
JOIN author AS a ON b.bookno = a.bookno
JOIN (
SELECT bookno FROM author
WHERE authorname in ('SQUARE', 'ENIX')
GROUP BY 1
HAVING count(*) = 2
) AS a2 ON b.bookno = a2.bookno;
/* this sQL will return only 2 and all matched authors: */
SELECT b.bookname, a.authorname
FROM book AS b
JOIN author AS a ON b.bookno = a.bookno
JOIN (
SELECT bookno FROM author
WHERE authorname in ('SQUARE', 'ENIX')
GROUP BY 1
HAVING count(*) = 2
) AS a2 ON b.bookno = a2.bookno
JOIN (
SELECT bookno FROM author
GROUP BY 1
HAVING count(distinct authorname) = 2
) AS a3 ON b.bookno = a3.bookno
PS1 - no need left join
PS2 - no need count distinct - unless your author table not design properly
If title is FANTASY genre is Adventure,fantasy, and search condition is
[ADVENTURE] = found
[FANTASY] = found
[ADVENTURE,FANTASY] = found
[ADVENTURE,FANTASY,ACTION] = not found
Then the SQL will be:
SELECT b.bookname, a.authorname
FROM book AS b
JOIN author AS a ON b.bookno = a.bookno
JOIN author AS a1 ON b.bookno = a1.bookno AND a1.authorname = 'SQUARE'
JOIN author AS a2 ON b.bookno = a2.bookno AND a2.authorname = 'ENIX'
Above is working, and I m wondering if there is a performance improvement

MySql count result from another table not return correct number

In my query i want to count how much user have photos and how much have pets. When i count how much pets he have that work good. When i try to count how much photos have than not work. He return me wrong result.
Full query is :
SELECT
acc.account_id,
CONCAT(acc.account_firstname,' ', acc.account_lastname) AS full_name,
acc.account_username AS username,
acc.account_website_url AS website,
g.gender_name AS gender,
acc.account_birthday AS birthday,
acc_t.account_type_name AS account_group,
(SELECT COUNT(*) FROM pb_account_photos WHERE owner_id = acc.account_id) AS photoCount,
(SELECT COUNT(*) FROM pb_account_photo_albums WHERE album_account_id = acc.account_id) AS photoAlbumCount,
CONCAT(country.country_name,'/',city.city_name) AS location,
COUNT(p.pet_id) AS petCount,
(SELECT CONCAT(s.value, '/uploads/user_data/',acc.account_id,'/photos/',photo.photo_guid, '/',.photo.photo_name) FROM pb_settings AS s WHERE s.key = 'siteurl') AS profile_picture,
(SELECT CONCAT(s.value, '/uploads/user_data/',acc.account_id,'/photos/',cover.photo_guid, '/',.cover.photo_name) FROM pb_settings AS s WHERE s.key = 'siteurl') AS cover_picture
FROM pb_accounts AS acc
LEFT JOIN pb_account_genders AS g ON g.gender_id = acc.account_gender_id
LEFT JOIN pb_animal_pets AS p ON p.pet_owner_id = acc.account_id
LEFT JOIN pb_account_types AS acc_t ON acc_t.account_type_id = acc.account_type_id
LEFT JOIN pb_locations AS loc ON loc.location_id = acc.account_location_id
LEFT JOIN pb_country AS country ON country.country_id = loc.location_id
LEFT JOIN pb_city AS city ON city.city_id = loc.city_id
LEFT JOIN pb_account_photos AS photo ON photo.photo_id = acc.profile_picture_id
LEFT JOIN pb_account_photos AS cover ON cover.photo_id = acc.profile_cover_picture_id
WHERE acc.account_id = 1 GROUP BY acc.account_id
Output
account_id full_name username website gender birthday account_group photoCount location petCount profile_picture cover_picture
---------- ---------------- -------- -------------- ------ ---------- ------------- ---------- -------------- -------- --------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------
1 Jon Doe jondoe013 www.google.com Male 2016-01-07 Administrator 2 Serbia/Belgrade 2 http://work.example.com/uploads/user_data/1/photos/9A5EF85E-F691-F42E-C20C-BCDC765BFA1B/6c28b264470e7a7f2829ea5b7290cbba.jpg http://work.example.com/uploads/user_data/1/photos/14B6D588-68E6-6783-324B-673CBCCD4FBC/6db0935929d08f7c51ded014bd9e73df.jpg
Problem:
Query return photoCount just 2 but i have 123 pictures. I also try to Group by for photo_id but not working.
Also in this case i use subquery and also try to remove subquery for photoCount and put COUNT(photo.*) AS photoCount and result is the same

MYSQL - Union SELECT & GROUP BY Not working

I have 3 table, log, member, also guest, but my log i stored as customer(user)'s id only, which is either their guest_id or member_id. So here's the problem, because they're from different table, I'm not sure how to join & group together their data.
checkout_log table
id user_id checkout_as
--------------------------------------
1 1 member
2 2 guest
members table
id fullname
--------------------------------------
1 member01
2 member02
guests table
id fullname
--------------------------------------
1 guest01
2 guest02
What I wanted to Achieve - Result
id user_id fullname checkout_as
----------------------------------------------
1 1 member01 member
2 2 guest02 guest
Had tried following sql statement with UNION ALL, or GROUP BY , but had no luck.
SELECT * FROM
(
SELECT checkout_log.id,checkout_log.user_id,guests.fullname,guests.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN guests ON checkout_log.user_id = guests.id
UNION ALL
SELECT checkout_log.id,checkout_log.user_id,members.fullname,members.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN members ON checkout_log.user_id = members.id
) derivedTable
GROUP BY id
Try doing this with joins instead of union
select cl.id, cl.user_id,
coalesce(m.fullname, g.fullname) as fullname,
cl.checkout_as
from checkout_log cl left join
members m
on cl.user_id = m.id and cl.checkout_as = 'member' left join
guests g
on cl.user_id = g.id and cl.checkout_as = 'guest';

Mysql join two tables with different row on left side and same row on right side

I have two table like this:
table1_ride
--------
id ride id
from_which_city city id
to_city city id
table2_city
--------
id city id
name city name
What I want is when I submit query SELECT * FROM ride I want to show me ride_id, from_which_city, to_city like this:
1 Manchester Liverpool
instead of
1 8 3 Where 8 = ManchesterID and 3 = LiverpoolID
I tried left join
SELECT * FROM ride LEFT JOIN city ON ride.from_which_city = city.id
and it's working for from_which_city. How to do this to work for both - from_which_city and to_city.
I didnt find case where left join is like: t1.b = t2.a AND t1.c = t2.a.
Thanks in advance!
Try this:
SELECT r.id, c1.name, c2.name
FROM table1_ride r
JOIN table2_city c1 on r.from_which_city=c1.id
JOIN table2_city c2 on r.from_which_city=c2.id
Use table aliases:
SELECT ride.id, fromcity.name, tocity.name
FROM ride
LEFT OUTER JOIN city fromcity ON ride.from_which_city = fromcity.id
LEFT OUTER JOIN city tocity ON ride.to_city = tocity.id
Join on the table2_city table twice and use an alias:
SELECT table1_ride.id, fc.name as from_city_name, tc.name as to_city_name
FROM table1_ride
INNER JOIN table2_city AS fc ON
table1_ride.from_which_city=fc.id
INNER JOIN table2_city AS tc ON
table1_ride.to_which_city=tc.id
(replace inner with left outer if necessary...).
SELECT c.id, m1.name, m2.name FROM mytabl1 as c, mytabl2 as m1, mytabl2 as m2
WHERE
c.cfrom = m1.city AND c.cto = m2.city
ORDER BY c.id
If I use above code below is what I get and this is what you were expected.
id name name
1 City 1 City 2
2 City 3 City 4
3 City 1 City 3
4 City 2 City 4