从GROUP BY组中选择具有特定内容的行

时间:2012-11-02 12:39:48

标签: mysql if-statement group-by row exists

我有两张表允许用户请求歌曲。当然,多个用户可以请求一首歌:

| Id | Song_Name |       | Requested_Id |  By_IP  |
+====+===========+       +==============+=========+
| 1  |   song1   |       |      1       | 1.1.1.1 |
| 2  |   song2   |       |      1       | 2.2.2.2 |
| 3  |   song3   |       |      1       | 3.3.3.3 |
                         |      2       | 2.2.2.2 |

为了防止一个用户多次请求歌曲(滥用),我需要检查用户是否已经请求过某个歌曲,而该歌曲只是试图再次请求它。所以我在第一个和第二个表之间进行LEFT JOIN,并在行GROUP BY之间进行Id,为每首歌返回一行。

问题GROUP BY会在未分组的字段上返回不可预测的值。这是众所周知的。但是,如果此组中存在此IP,我如何确保SELECT返回包含特定IP的行?如果IP不存在,则SELECT可以返回该组的任何其他行。

非常感谢!

更新:我需要在列表中显示歌曲,而不管有多少用户(甚至根本没有用户)请求它。所以SELECT肯定需要为每首歌返回一行。但是,例如,具有IP 3.3.3.3的用户试图请求song1(已经由他请求),我希望查询返回:

| Id | Song_Name |  By_IP  |
+====+===========+=========+
| 1  |   song1   | 3.3.3.3 |  (3.3.3.3 in case it exists, otherwise anything else)
| 2  |   song2   | 2.2.2.2 |

我还需要与其他请求(IP)进行分组,因为我还需要获得每首歌曲的全部请求数。因此我使用Count()。

替代方法:由于执行我需要的工作(如果可能的话)似乎相当复杂,我现在正在使用一种解决方法。我正在使用GROUP_CONCAT()聚合函数。这为我提供了以“,”分隔的该组的所有IP。所以我可以搜索我正在搜索的那个是否已存在。唯一的缺点是,这个返回字符串的(默认)最大长度是1024.这意味着我无法处理大量用户,但现在它应该没问题。

3 个答案:

答案 0 :(得分:1)

目前还不清楚你想要什么?表中没有要求的日期。如果没有日期,你怎么知道特定歌曲何时被请求。


Select Songs.id, Songs.Song_name, requested_songs.By_IP 
from Songs 
 INNER JOIN requested_songs 
    on Songs.id = requested_songs.Requested_id
    Group BY requested_songs.Requested_id
order by requested_songs.Requested_id ASC
; 

<强> SQLFiddle Demo:

答案 1 :(得分:0)

只需使用Song_Name和By_IP进行分组。喜欢这个

SELECT * FROM  `songs` JOIN users GROUP BY song_name, ip

答案 2 :(得分:0)

你确定你没有过度思考你的解决方案吗?如果您只想消除重复项,只需在第二个表的两列上放置一个UNIQUE索引。

如果您尝试使用GROUP BY执行更复杂的操作,请提供Quassnoi请求的示例结果集。