简体   繁体   English

我在MySQL中有4个表-与没有重复的第4个表联接(可能为null值)

[英]I have 4 tables in MySQL - Join with 4th table without duplicates (possible null value)

Ok I am working with 4 tables and I need my query to return no duplicates and null value if needed. 好的,我正在处理4个表,我需要查询不返回任何重复项,如果需要,则返回null值。 Unfortunately due to a restriction in the framework I am using I can not use UNION. 不幸的是,由于我使用的框架存在限制,因此无法使用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: 上面的查询为我提供了john用户的song_history中所有歌曲的列表:

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 上面的查询为我提供了song_history中所有在song_current表中还为event_id为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. 现在,由于我使用的框架,我受到了限制,这限制了我使用UNION,所以我迷失了没有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. 基本上,我需要一个给定用户在song_history表中的所有歌曲的列表,如果event_id匹配,则需要显示event_id;如果不匹配,则需要显示null,但仍显示在song_history表。

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. song_history表将始终包含song_current中的内容(没有event_id),但是,song_current并不总是包含在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. 如果可以使用UNION,我将简单地使用上面两个成功的查询,并且可以解决我的问题,但是,由于我不能使用UNION,所以我对LEFT INNER,LEFT OUTER和其他JOINS的所有尝试都使我望而却步。

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: 请注意,song_current表将具有其他event_id,这将使我无法像这样使用WHERE / OR:

AND (event_id = 20 OR event_id IS NULL); AND(event_id = 20 OR event_id为NULL);

The Joomla 3.3 Framework just recently included the UNION statement and it does not work on multiple columns at this time. Joomla 3.3框架最近才包含UNION语句,目前无法在多个列上使用。

Here is an example of a somewhat working UNION query that works fine in phpMyAdmin: 这是一个在phpMyAdmin中可以正常工作的UNION查询的示例:

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. 注意:还有一个名为users.ordering的附加列,该列始终返回0,上面没有列出-我正在使用它为没有event_id的歌曲赋予0值。

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. 请记住,此UNION查询有效,但有一个例外(尽管我可以接受),它为event_id为0的用户列出了song_history中的所有歌曲,然后再次列出了song_history和song_current以及匹配的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 您可能需要做的就是删除event_id上的过滤条件,或者也包括NULL event_id,如下所示

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. SQL Fiddle演示第三个查询包括具有NULL event_id的行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM