Ok I am working with 4 tables and I need my query to return no duplicates and null value if needed. Unfortunately due to a restriction in the framework I am using I can not use UNION. Here are my tables:
users Table
------------------------------------------------------
id name
------------------------------------------------------
1 jane
2 john
3 skip
songs Table
------------------------------------------------------
id artist title
------------------------------------------------------
1 devo whip
2 snake hiss
3 america great
4 elvis blues
song_history Table
------------------------------------------------------
singer_id song_id
------------------------------------------------------
2 1
2 2
2 3
2 4
song_current Table
------------------------------------------------------
singer_id song_id event_id
------------------------------------------------------
2 3 20
2 4 22
I have written two queries that work for half of the results needed, here is the first one:
SELECT name, artist, title
FROM users AS user
LEFT JOIN song_history AS history ON user.id = history.singer_id
LEFT JOIN songs AS song ON history.song_id = song.id
WHERE user.id = 2
The above query gives me a list of all the songs in song_history for user john:
name artist title
-----------------------------
john | devo | whip |
john | snake | hiss |
john | america | great |
Here is the second query for the other half of the results needed:
SELECT name, artist, title, event_id
FROM users AS user
LEFT JOIN song_history AS history ON user.id = history.singer_id
LEFT JOIN songs AS song ON history.song_id = song.id
LEFT JOIN song_current AS csongs ON csongs.singer_id = user.id
AND csongs.song_id = history.song_id
WHERE user.id = 2
AND event_id = 20
The above query gives me a list of all the songs in song_history that are ALSO in the song_current table with event_id of 20
name artist title event_id
--------------------------------------------
john | america | great | 20
Now, I have a restriction due to the framework I am using that restricts me from using UNION so I am lost as to how or if there is a way to do this without UNION.
Here are the results I am looking for:
name artist title event_id
-------------------------------------
john | devo | whip | null
john | snake | hiss | null
john | america | great | 20
john | elvis | blues | null
Basically I need a list of all songs for a given user that are in the song_history table and if an event_id matches it needs to show the event_id, if it does not match then it needs to show null but still show the songs that are in the song_history table.
The song_history table will always contain what is in song_current (without the event_id) however, song_current will not always contain data that is found in song_history.
If I could use UNION, I would simple use the two successful queries above and my problem would be solved, however, since I can't use UNION then all my attempts at LEFT INNER, LEFT OUTER and other JOINS have eluded me.
Any help is greatly appreciated!
Edited:
Note that the song_current table will have other event_id's that will keep me from using a WHERE/OR like this:
AND (event_id = 20 OR event_id IS NULL);
The Joomla 3.3 Framework just recently included the UNION statement and it does not work on multiple columns at this time.
Here is an example of a somewhat working UNION query that works fine in phpMyAdmin:
NOTE: there is an additional column called users.ordering that always returns 0 that is not outlined above - i was using this to give a 0 value to songs that did not have an event_id.
SELECT name, artist, title, users.ordering AS event_id
FROM users, song_history, song_current
WHERE users.id = song_history.singer_id
AND song_history.song_id = songs.id
AND users.id = '2'
UNION
SELECT name, artist, title, song_current.event_id AS event_id
FROM users, song_current, songs
WHERE users.id = song_current.singer_id
AND song_current.song_id = songs.id
AND users.id = '2'
AND song_current.event_id = '20'
Keep in mind that this UNION query works but with one exception (albeit acceptable for my use) It lists all the songs in the song_history for the user with a 0 event_id then it lists all the songs again that are both in the song_history and in the song_current along with the matching event_id. This result would be just as acceptable as the results listed above.
All you probably need is to either remove the filter condition on event_id or include NULL event_id's as well, as below
SELECT name, artist, title,
CASE
WHEN event_id <> 20 THEN NULL
ELSE event_id
END event_id
FROM users AS user
LEFT JOIN song_history AS history ON user.id = history.singer_id
LEFT JOIN songs AS song ON history.song_id = song.id
LEFT JOIN song_current AS csongs ON csongs.singer_id = user.id
AND csongs.song_id = history.song_id
WHERE user.id = 2
SQL Fiddle demo The third query includes the rows with NULL event_id.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.