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.
Related
I'm really struggling to get my head around this. I am trying to run a SELECT query from multiple tables.
This is what I have so far that doesn't work;
SELECT jira_issues.*, session_set.* FROM jira_issues, session_set
INNER JOIN reports on jira_issues.report_id = reports.id
WHERE jira_issues.report_id = 648
I have other tables (session_set, report_device) which has a ReportID and report_id column respectively.
I have a report table which has a Primary Key id. In the other tables the report.id key is linked with foreign keys.
Ultimately what I am trying to achieve is this:
I have an entry in the reports table with an id of 648. In the other tables (jira_issues, report_device, session_set), I also have entries which has a foreign key linked to the report id in the report table.
I want to run one SELECT Query to query the tables (jira_issues, report_device and session_set) and get all the data from them based on the report.id.
Thanks!
What about this:
SELECT * FROM jira_issues ji
LEFT JOIN session_set ss ON ji.report_id = ss.ReportID
LEFT JOIN report_device rd ON rd.report_id = ji.report_id
WHERE ji.report_id = 648;
Just say "no" to commas in the from clause. Always use explicit join syntax:
SELECT ji.*, session_set.*
FROM jira_issues ji inner join
reports r
on ji.report_id = r.id inner join
session_set ss
on ss.ReportId = r.report_id
WHERE ji.report_id = 648;
If some of the tables might have no corresponding rows, you might want left outer join instead of inner join.
Kindly try this out. You may get syntax error.
SELECT a., b. FROM jira_issues a, session_set b, reports c
Where a.report_id = c.id and b.report_id = c.id AND a.report_id = 648
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
I'm working on displaying the achievements from my minecraft server on my website.
But I can't get it to work.
function achievements() {
global $id;
$sql="SELECT * FROM achievements
INNER JOIN stats ON achievements.type=stats.type
INNER JOIN stats ON achievements.block=stats.block
INNER JOIN stats ON achievements.data=stats.data
INNER JOIN stats ON achievements.value=stats.value
WHERE player_id = $id";
$result=mysql_query($sql) or die(mysql_error());
$rows=mysql_fetch_array($result);
}
Will I be able to use $rows['achievements.type']; and $rows['stats.type']; to get the column "type" from the selected table, or is there a another way to do it?
The column and table names are defined by the plugin I use, so the names can't be changed.
the reason why it is not working is because (in my own opinion) the server is a little confused on where how it will handle the columns names properly. In order it to work, add an alias on every table that has the same name that you want to join as well as the columns, eg
SELECT achievements.*,
a.Name as TypeName,
b.Name AS BlockName,
c.Name as DataName,
d.Name AS ValueName
FROM achievements
INNER JOIN stats a ON achievements.type = a.type
INNER JOIN stats b ON achievements.block = b.block
INNER JOIN stats c ON achievements.data = c.data
INNER JOIN stats d ON achievements.value = d.value
WHERE player_id = $id
assuming you want to get the names for every specific columns.
Give the columns you want to have while you SELECT them an alias as example:
SELECT `achievements`.`type` AS `Achieve-Type`
FROM `achievements`
Now you can get the values like this: $rows['Achieve-Type'];
It's easier to alias the table names with...
SELECT * FROM achievements AS ac INNER JOIN stats as st
You could even alias the results if you wish so they are more distinguishable when you select them from $rows
Ok this (truncated query) runs fine. Got some expert advice a month ago to fix it.
SELECT * FROM artWork WHERE art_id in (
SELECT art_id FROM artWork AS a INNER JOIN userPrefs AS u ON ((
((u.media_oil='1' AND a.media_oil='1') OR
(u.media_acrylic='1' AND a.media_acrylic='1') OR
(u.media_wc='1' AND a.media_wc='1') OR
(u.media_pastel='1' AND a.media_pastel='1'))
etc, etc........................................
WHERE a.artist_id NOT EXISTS (
SELECT * FROM removeList AS r
WHERE r.artist_id = a.artist_id
AND r.user_id ='$user_id')
AND a.make_avail='1'
AND a.cur_select='1'
AND u.user_id='$user_id'
AND ((u.pref_painting='1' AND a.pref_painting='1') OR
(u.pref_photo='1' AND a.pref_photo='1') OR
(u.pref_paper='1' AND a.pref_paper='1') OR
(u.pref_print='1' AND a.pref_print='1') OR
(u.pref_draw='1' AND a.pref_draw='1') OR
(u.pref_sculp='1' AND a.pref_sculp='1') OR
(u.pref_install='1' AND a.pref_install='1') OR
(u.pref_vid='1' AND a.pref_vid='1') OR
(u.pref_public='1' AND a.pref_public='1') OR
(u.pref_indef='1' AND a.pref_indef='1'))
) ORDER BY date_submit DESC
But now I need to exclude certain rows that may be in another 2 column (user_id & artist_id) child table: 'removeList'. So I am trying without success to what amounts to a "triple join" (look for the code around 'NOT EXISTS'):
SELECT * FROM artWork WHERE art_id in (
SELECT art_id FROM artWork AS a INNER JOIN userPrefs AS u ON (
(((u.media_oil='1' AND a.media_oil='1') OR
(u.media_acrylic='1' AND a.media_acrylic='1') OR
(u.media_wc='1' AND a.media_wc='1') OR
(u.media_pastel='1' AND a.media_pastel='1'))
etc, etc........................................
WHERE a.artist_id NOT EXISTS (
SELECT * FROM removeList AS r
WHERE r.artist_id = a.artist_id AND r.user_id ='$user_id'
)
AND a.make_avail='1'
AND a.cur_select='1'
AND u.user_id='$user_id'
AND (( u.pref_painting='1' AND a.pref_painting='1') OR
( u.pref_photo='1' AND a.pref_photo='1') OR
( u.pref_paper='1' AND a.pref_paper='1') OR
( u.pref_print='1' AND a.pref_print='1') OR
( u.pref_draw='1' AND a.pref_draw='1') OR
( u.pref_sculp='1' AND a.pref_sculp='1') OR
( u.pref_install='1' AND a.pref_install='1') OR
( u.pref_vid='1' AND a.pref_vid='1') OR
( u.pref_public='1' AND a.pref_public='1') OR
( u.pref_indef='1' AND a.pref_indef='1') )
) ORDER BY date_submit DESC
Am I reaching too far here? Is there a better approach I am overlooking. Thanks to all.
NOT EXISTS shouldn't have a column name before it. remove the a.artist_id from before the not exists.
So the relevant line would say
WHERE NOT EXISTS (
SELECT * FROM removeList AS r
WHERE r.artist_id = a.artist_id AND r.user_id ='$user_id'
)
Not sure where you're using this query, but its also recommended to parameterize your queries to prevent sql injections.
Hope this helps!
i know this is not an answer, but i could not place a table within the comments so i am putting it here.
i feel like extra tables to hold your media and prefs is needed here to greatly simplify things in your database.
media_table
id, user_id, media_type
prefs_table
id, user_id, pref_type
Then fields in your art table that correlate to a media type, and pref type.
art_table
media_type, art_type
This way you could easily use a simple JOIN to find correlating records instead of those hundreds of comparisons.
SELECT art.id FROM art JOIN prefs_table ON art.pref_type = prefs_table.pref_type JOIN users ON prefs_table.user_id = users.id WHERE users.id = whatever
This is a simplified example that would pull up all peices of art that matched any one of the user's preferences. You could of course easily incorporate media types as well into the same query in the same fashion.
You need to do some serious work on your schema, along the lines suggested by dqhendricks.
You have 3 tables:
ArtWork (Art_ID, Artist_ID, ...characteristics...)
UserPrefs (User_ID, ...characteristics...)
RemoveList (Artist_ID, User_ID)
You want to list art works which match the user preferences of a specific user, but do not want to list any art works where the artist dislikes the user or the user dislikes the artist (or both).
You should, therefore, be able to do something like:
SELECT A.*
FROM ArtWork AS A
JOIN UserPrefs AS U
ON (U.User_ID = ? AND (...ghastly OR'd join conditions...))
WHERE A.Artist_ID NOT IN (SELECT R.Artist_ID
FROM RemoveList AS R
WHERE R.User_ID = ?)
Note that you can move some of the join conditions into the WHERE clause, and various other changes, but the basic structure of the query will be a JOIN of ArtWork and UserPrefs and a WHERE clause with the NOT IN clause (which you could write as a NOT EXISTS clause, but I think the NOT IN formulation is easier to read).