【问题标题】:Limit number of MySQL results per user限制每个用户的 MySQL 结果数
【发布时间】:2014-01-29 10:19:45
【问题描述】:

我有一个网站,用户可以在其中列出待售商品。网站正面使用以下 SQL 显示随机特卖商品。

SELECT * FROM auctions 
WHERE closed = 0 AND suspended = 0 AND starts <= 1390990443
ORDER BY RAND() LIMIT 30

问题在于,一个用户的销量很大,以至于网站的前端大多是那个用户。我想将用户使用auction.user 列显示的项目限制为每个用户五个项目。

我希望有 SQL 可以在一行中执行此操作,如果没有的话,将不胜感激有关谁在多个查询上建立结果的建议或链接。编码语言为 PHP。

编辑:数据库结构在这里。 http://pastebin.com/3ua18k4h

【问题讨论】:

  • 你可以为每个用户运行上面的sql并附加限制5
  • @SatishSharma - 哦,是的,这是一个很棒的计划! (不)
  • 6个查询解决一个问题?可能有更聪明的方法。
  • @Strawberry OP 使用 php。它可以很容易地制作。你有更好的选择吗
  • Bushtar,考虑提供适当的 DDL 和一些具有代表性的数据(最好是 sqlfiddle)以及几个示例结果集

标签: php mysql sql mysqli


【解决方案1】:

我个人会尝试形成一些解决方案,将结果拉入 PHP 并在那里过滤它们,但那是因为我觉得 PHP 比 MySQL 更舒服。但是,您可以在没有 PHP 过滤的情况下仅通过 MySQL 查询执行此类操作,但不知道如何扩展到大量用户(不确定您的完整表架构,所以我即兴创作)

SELECT ID, USERNAME, AUCTION_ID
FROM
(
  SELECT *, @row:=IF(username=@username,@row,0)+1 AS auctioncount, @username:=username FROM 
  (SELECT *,RAND() AS trand FROM table1) t1,
  (SELECT @row:=0,@username:='') tm2 
  ORDER BY username,trand
) t2
WHERE auctioncount<=5 LIMIT 30

SQL 小提琴:http://sqlfiddle.com/#!2/9bd47/1

您可以将auctioncount 更改为您希望每个用户拥有的最大列表数。

【讨论】:

  • 太好了,感谢您的代码。我现在将它放在网站上,这正是我所需要的。
  • @Bushstar 只是出于兴趣(如果您能找到的话),这个查询在您的约 1,500 行数据集上需要多长时间?
  • 使用分析器运行它,我可以看到持续时间是 0.34166050,我认为是以秒为单位。
  • *************************** 1. 行 ************ ****************** Query_ID:1 持续时间:0.34166050
【解决方案2】:

您可以使用具有更大 LIMIT 的 MYSQL 获得更多结果,然后为每个用户创建一个待售商品的数组,最后每个用户只需要 5 个商品,因此您将只使用 1 个对 Mysql 的请求和更多的 CPU 使用率,可以如果您的网站有大量流量,这是一个好主意。

1) 获得更多结果:

SELECT * FROM auctions 
WHERE closed = 0 AND suspended = 0 AND starts <= 1390990443
ORDER BY RAND() LIMIT 1000

2) 每个用户的每个项目循环和存储:

foreach($results as $item) {
   array_push($itemsPerUser[$item['userId']], $item);
}

3) 每个用户仅过滤 5 个项目:

foreach($itemsPerUser as $user => $items) {
   $fiveItemsPerUser = array_slice($items, 0, 5);
}

P.S: 这是伪代码,你应该对数组长度等进行更多检查...

【讨论】:

    【解决方案3】:

    不是很直接地回答你的问题,但也许以下就足够了:

    随机选择 30 个正在进行拍卖的用户,并显示每个用户中最早的拍卖:

    SELECT * FROM auctions WHERE id IN (
        SELECT MIN(id) FROM auctions
        WHERE closed = 0 AND suspended = 0 AND starts <= 1390990443
        GROUP BY userid ORDER BY RAND() LIMIT 30
    )
    

    至少您可以删除换行符并将其全部包含在单行 sql 查询中,这无法通过您请求的确切查询来完成。

    【讨论】:

    • 谢谢,这是一个有趣的选择。
    【解决方案4】:

    这里有一些需要考虑的事情,尽管我很欣赏从这个到(公平和)可行的解决方案的智力飞跃可能有点过头了!...

    SELECT RAND(@i:=RAND()*1000);
    +-----------------------+
    | RAND(@i:=RAND()*1000) |
    +-----------------------+
    |    0.7903550134881911 |
    +-----------------------+
    
    SELECT RAND(@i);
    +--------------------+
    | RAND(@i)           |
    +--------------------+
    | 0.7903550134881911 |
    +--------------------+
    
    SELECT RAND(@i:=RAND()*1000);
    +-----------------------+
    | RAND(@i:=RAND()*1000) |
    +-----------------------+
    |    0.9555754568014065 |
    +-----------------------+
    

    【讨论】:

      猜你喜欢
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      • 2015-10-05
      • 2012-07-23
      • 1970-01-01
      相关资源
      最近更新 更多