从 GROUP BY 组中选择具有特定内容的行
Posted
技术标签:
【中文标题】从 GROUP BY 组中选择具有特定内容的行【英文标题】:Select a row with specific content from a GROUP BY group 【发布时间】:2012-11-02 12:39:47 【问题描述】:我有两个表允许用户请求歌曲。当然,多个用户可以请求一首歌曲:
| 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
,并在行的Id
旁边做一个GROUP BY
,它为每首歌返回一行。
问题:GROUP BY
在未分组的字段上返回不可预测的值。这是众所周知的。但是,如果该 IP 存在于该组中,我如何确保 SELECT
返回包含特定 IP 的行?如果IP不存在,则SELECT
可以返回该组的任何其他行。
非常感谢!
更新:我需要在列表中显示这首歌,与有多少用户(甚至根本没有用户)请求它无关。所以 SELECT 肯定需要为每首歌曲返回一行。但是,如果 IP 3.3.3.3 的用户尝试请求歌曲 1(他已经请求过),我希望查询返回以下内容:
| 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。这意味着我无法处理大量用户,但现在应该没问题。
【问题讨论】:
您希望查询返回什么?请发布示例结果集。 【参考方案1】:目前还不清楚你想要什么?表中没有要求的日期。没有日期,您如何知道何时请求了特定歌曲。
选择 Songs.id、Songs.Song_name、requested_songs.By_IP 从歌曲 INNER JOIN 请求_歌曲 在 Songs.id = requested_songs.Requested_id Group BY requested_songs.Requested_id 按 request_songs.Requested_id ASC 排序 ;SQLFiddle Demo:
【讨论】:
这会返回我对某首歌曲的所有请求。这意味着多行。但我每首歌只需要一行。 嗨!我不需要知道“何时”请求了一首歌曲,我只需要知道特定用户是否已经请求了那首歌曲。为此,我将请求用户的 IP 和歌曲 ID 一起输入到第二个表中(见上文)。【参考方案2】:您确定您没有过度考虑您的解决方案吗?如果您只想消除重复项,只需在第二个表的两列上都放置一个UNIQUE
索引。
如果您想用 GROUP BY
做一些更复杂的事情,请按照 Quassnoi 的要求提供一个示例结果集。
【讨论】:
【参考方案3】:只需按 Song_Name 和 By_IP 分组即可。像这样
SELECT * FROM `songs` JOIN users GROUP BY song_name, ip
【讨论】:
这对我不起作用,因为我仍然需要计算任何 Id 的请求总数。因此,我需要使用 GROUP BY 和 Count() 的可能性另一方面,据我所知,JOIN 仅在两个表中都存在 Id 的情况下才连接行。以上是关于从 GROUP BY 组中选择具有特定内容的行的主要内容,如果未能解决你的问题,请参考以下文章