I have the id of an album and I'd like to get all the tracks from an album with their artists. An album has many tracks. A track has many producers (artists).
MySQL Structure
Problem
I don't know if I can do it in full mySQL or if I should add some PHP instead.
EDIT : My question wasn't clear enough. The problem wasn't the fact of doing a query with joined table but to get the tracks with a list of the artists. You can handle that with group_concat.
Tutorial : http://www.mysqlperformanceblog.com/2006/09/04/group_concat-useful-group-by-extension/
It depends how you need the data. If you're more interested in the artists then you can join tracks on albums and then artists onto tracks. This will give you a record for each artist.
SELECT
ar.*
FROM albums AS al
JOIN tracks AS t
ON t.album_id = al.album_id
JOIN produced AS p
ON p.produced_track = t.track_id
JOIN artists AS ar
ON ar.artist_id = p.produced_artist
If you're more interested in the tracks and just need to list the artists then do the same join but use group_concat on the artist name and group by the track id
SELECT
t.*,
GROUP_CONCAT(DISTINCT ar.name ORDER BY ar.name SEPARATOR ', ') AS artists
FROM albums AS al
JOIN tracks AS t
ON t.album_id = al.album_id
JOIN produced AS p
ON p.produced_track = t.track_id
JOIN artists AS ar
ON ar.artist_id = p.produced_artist
GROUP BY t.track_id
Learn about SQL joins:
SELECT *
FROM Tracks
JOIN Produced ON Produced.produced_track = Tracks.track_id
JOIN Artists ON Artists.artist_id = Produced.produced_artists
WHERE Tracks.track_album = ?
It's probably best just to do this in pure SQL like so:
SELECT *
FROM albums al
LEFT JOIN tracks tr ON (tr.ttack_album = al.album_id)
LEFT JOIN produced pr ON (pr.produced_track = tr.track_id)
LEFT JOIN artists ar ON (ar.artist_id = pr.produced_artist)
WHERE al.album_id = thealbumid;
However there's nothing preventing you from doing separate queries depending on how you need to use the data.
You can, and you should, do that with pure MySQL, have three tables, link them with foreign keys, and query using JOINs.
You don't need PHP to overload the work, MySQL can handle it just fine :)
You can use LEFT JOIN to achieve this with mysql only:
SELECT * FROM Albums a
LEFT JOIN Tracks b
ON a.album_id = b.track_album
LEFT JOIN Produced c
on b.track_id = c.produced_track
LEFT JOIN Artist d
on c.produced_artist = d.artist_id
WHERE a.album_id = ?
You could do it in SQL using aggregate functions and group by clause.
It should look like:
select t.*,
some_aggregate_function(a.whatever)
from Tracks t
left join Produced p on (t.trac_id = p.produced_id)
left join Artist a on (p.produced_artist = a.artist_id)
group by t.*
Related
Please i have four tables joined together using the LEFT JOIN, the images table is linked to the items table by img_item, thus each item can have more images. i want to fetch only the first image of every item. How do i go achieve this.
SELECT * FROM items
LEFT JOIN category ON items.item_cat = category.cat_id
LEFT JOIN users ON users.user_id=items.item_user
LEFT JOIN institutions ON institutions.inst_id=users.user_inst
LEFT JOIN images ON images.img_item = items.item_id
ORDER BY item_id DESC
In MySQL, you can enumerate the results using variables, and then choose the first. Another alternative is to identify which one you want, and choose that one. The following chooses the image with the largest id:
SELECT *
FROM items LEFT JOIN
category
ON items.item_cat = category.cat_id LEFT JOIN
users
ON users.user_id=items.item_user LEFT JOIN
institutions
ON institutions.inst_id = users.user_inst LEFT JOIN
images
ON images.img_item = items.item_id AND
images.img_id = (SELECT MAX(i2.img_id)
FROM images i2
WHERE i2.img_item = images.img_item
);
ORDER BY item_id DESC
I'm working on a project that each orgnizations have barriers, each organization can contain 1 or more barriers, and then I need generate an XML file that show each barrier into the organization .
But executing this sql code:
SELECT organizations.*, barriers.barrierName AS bname, barriers.type AS btype, geographs.name AS geo, rpd.rpdname AS rpdn, rpd.meaning AS rpdmean FROM organizations
left join orgbarriers on orgbarriers.idOrg = organizations.id
left join barriers on orgbarriers.idBarrier = barriers.id
left join orggeographs on organizations.id = orggeographs.idOrg
left join geographs on geographs.id = orggeographs.idGeo
left join orgrpds on orgrpds.idOrg = organizations.id
left join rpd on rpd.id = orgrpds.idRPD
I get repeated rows like this image:
Use the keyword "DISTINCT"
SELECT DISTINCT rest of your query
I have the following query which works perfectly:
SELECT *
FROM contacts
WHERE id in (
SELECT DISTINCT contacts.id
FROM contacts
INNER JOIN contacts2tags
ON contacts.id = contacts2tags.contactid
WHERE tagid in(7,4)
)
Here contacts table contains id, first_name, last_name, ..and tags table contains id, name. contacts2tags table contains contactid and tagid which are same as contacts.id and tags.id respectively
Now, what I want is, to display only the contacts which have both a tagid 7 and a tagid 4.
I tried something like this:
SELECT *
FROM contacts
WHERE id IN
(
SELECT CT1.contactid
FROM
tags T1, contacts2tags CT1, tags T2, contacts2tags CT2
WHERE CT1.contactid = CT2.contactid
AND CT1.tagid = T1.id
AND CT2.tagid = T2.id
AND (T1.id = 7 AND T2.id = 4)
and it works too.
My problem is, I want to convert the above second query to one using inner joins.
I have an array of ids stored in $tmp in php
I want to use those ids and write the above query for them.
How do I do that? I am not comfortable with sql. Might be its a very simple thing to ask.
Thanks in advance
EDIT:
The answer below solved the problem. But the sql runs very slow for 10k records. Any suggestions to optimise it? Pasting the updated query as given in the answer.
SELECT c.id
FROM contacts c
inner join contacts2tags t on c.id = t.contactid
where t.tagid in (7,4)
group by c.id
having count(distinct t.tagid) = 2
This should work
SELECT c.id
FROM contacts c
inner join contacts2tags t on c.id = t.contactid
where t.tagid in (7,4)
group by c.id
having count(distinct t.tagid) = 2
I have a MYSQL query who have to list all post i want it to post. But it dont do it. It shows posts when i have more then one post in the table "meaOrder" with the same "ordCode". But when i have only on post in meaOrder, i don't show it. What can i do?
SELECT koden, wish, rnamn, bild, pris, cname, onsktext
FROM (
SELECT m.wishText as onsktext, m.meaOID as midn, m.ordcode as koden, w.wish as wish, r.meaName as rnamn, r.meaImg as bild,
r.meaPrice as pris, k.catName as cname from cats k, meals r, wishes w,
meaOrder m
join orders c on c.ordNR=4401
WHERE c.ordStatus=1 AND m.ordNR=c.ordNR AND m.meaID=r.meaID AND m.wishesID=w.id
AND r.catID=k.catID
) T
GROUP BY koden, rnamn, bild, pris, cname
ORDER BY midn DESC
TABLE orders
http://grab.by/m74E
TABLE meaOrder http://grab.by/m74Q
Try replacing the JOIN with RIGHT JOIN in this case. The difference is explained at JOIN Syntax page in MySQL docs . In short - JOIN returns row only if there are corresponding rows in both joined tables (inner join). LEFT JOIN / RIGHT JOIN return all rows from one of the tables and corresponding row if it exists from the other table (those are outer joins)
Do you need a subselect?
This seems to cover it:-
SELECT m.ordcode AS koden, w.wish AS wish, r.meaName AS rnamn, r.meaImg AS bild, r.meaPrice AS pris, k.catName AS cname, m.wishText AS onsktext
FROM cats k
INNER JOIN meals r ON r.catID = k.catID
INNER JOIN meaOrder m ON m.meaID = r.meaID
INNER JOIN wishes w ON m.wishesID = w.id
INNER JOIN orders c ON m.ordNR = c.ordNR
WHERE c.ordStatus = 1
AND c.ordNR = 4401
GROUP BY m.ordcode, r.meaName, r.meaImg, r.meaPrice, k.catName
ORDER BY midn DESC
Ok so i want to get an artists info from the db, but i want to know if they have any forthcoming events. To do this i need to traverse 2 tables, where events_artists is a 2 col link table...
(this doesnt work but is what id like to do)
SELECT art.*, events.event_id FROM art
LEFT JOIN events_artists
ON art.art_id = events_artists.art_id
LEFT JOIN events
ON events_artists.event_id = events.event_id IF ( {criteria} )
what should i be doing here to get this to work?!!
You can use the AND keyword to specify additional criteria on the join.
SELECT art.*, events.event_id FROM art
LEFT JOIN events_artists
ON art.art_id = events_artists.art_id
LEFT JOIN events
ON events_artists.event_id = events.event_id AND ( {criteria} )
If necessary, you could also use a subquery such as AND EXISTS (SELECT * FROM tbl) if you need to query additional data.