【问题标题】:Mysql Limit column value repetition N timesMysql限制列值重复N次
【发布时间】:2010-06-14 14:22:08
【问题描述】:

我有两张桌子

Customer (idCustomer, ecc.. ecc..)
Comment (idCustomer, idComment, ecc.. ecc..)

显然这两个表是连接在一起的,例如

SELECT * FROM Comment AS co
  JOIN Customer AS cu ON cu.idCustomer = co.idCustomer

有了这个,我从与客户关联的表格中选择所有评论,但现在我想将评论的数量限制为每个客户最多 2 条评论。

我看到的第一件事是使用GROUP BY cu.idCustomer,但它限制每个客户只有 1 条评论,但我希望每个客户有 2 条评论。

我怎样才能做到这一点?

【问题讨论】:

    标签: php mysql group-by


    【解决方案1】:

    MySQL 中的一个选项是服务器端变量。例如:

    set @num := 0, @customer := -1;
    
    select  *
    from    (
            select  idCustomer
            ,       commentText
            ,       @num := if(@customer = idCustomer, @num + 1, 1) 
                        as row_number
            ,       @customer := idCustomer
            from    Comments
            order by 
                    idCustomer, PostDate desc
            ) as co
    join    Customer cu
    on      co.idCustomer = cu.idCustomer
    where   co.row_number <= 2
    

    【讨论】:

    • 似乎没有其他不同的方式..我对此有点难过..我看到了很多例子,但似乎这是最好的解决方案。我接受它,有点悲伤,我更喜欢更优雅的解决方案:(在这种模式下提取数据,你建议不同或更好的数据库布局?
    • @Paper-bat:其他数据库支持更优雅的解决方案。但是 MySQL 在子查询中存在limit 的问题,并且不支持row_number()。我认为您的数据库布局很好
    • 这一行 @customer = idCustomer 不应该是 @customer := idCustomer ??
    【解决方案2】:

    此版本不需要 SET 操作:

    select  *
    from    (select  idCustomer
             ,       commentText
             ,       @num := if(@customer = idCustomer, @num + 1, 1) as row_number
             ,       @customer = idCustomer
             from    Comments
             JOIN(SELECT @num := 0, @customer := 1) r
             order by idCustomer, PostDate desc) as co
     join    Customer cu on co.idCustomer = cu.idCustomer
     where   co.row_number <= 2
    

    【讨论】:

      【解决方案3】:
      SELECT * FROM Comments AS cm1 
               LEFT JOIN Comments AS cm2 ON cm1.idCustomer = cm2.idCustomer 
               LEFT JOIN Customer AS cu ON cm1.idCustomer = cu.idCustomer
      WHERE cm1.idComment != cm2.idComment
      GROUP BY cm1.idCustomer
      

      但是,如果要更改 cmets 的数量,最好使用Andomar 的解决方案。

      【讨论】:

      • mh.. 还不错.. :) 在我的国家(意大利)被用来命名它,作为 'barbatrucco' :P 把它翻译成一个聪明的把戏 ^^
      【解决方案4】:

      不用游标,很慢。请参阅我对Complicated SQL Query About Joining And Limitting 的回答。 DENSE_RANK 可以解决所有复杂的光标问题。

      【讨论】:

        【解决方案5】:

        如果您使用诸如 PHP 之类的脚本语言来处理结果,您可以在运行查询后限制每个客户显示的结果数量。设置一个数组来保存所有结果,设置另一个数组来保存每个客户的结果数量,并在计数超过您的限制后停止将查询结果添加到结果集中,如下所示:

        $RESULTS = array();
        $COUNTS = array();
        $limit = 2;
        $query = "SELECT customer_id, customer_name, customer_comment FROM customers ORDER BY RAND()";
        $request = mysql_query($query); 
        while ($ROW = mysql_fetch_assoc($request))
        {
            $c = $ROW['customer_id'];
            $n = $COUNTS[$c];
            if ($n<$limit)
            {
                 $RESULTS[] = $ROW;
                 $COUNTS[$c]++;
            }
        }
        

        这保证了每个客户只会随机抽取两个 cmets,或者根据您的需要,其余的会被丢弃。当然,您正在提取所有结果,但这(可能)比进行复杂连接要快。

        【讨论】:

        • 我想只使用一个sql查询,因为在阅读代码时更快更清晰,并且当您将来需要更新代码时,您可以简单地修改您的sql,对脚本代码稍作改动.这就是为什么我在创建 sql 查询时花费大量时间,更具体的查询,更少的代码,最后你可以学到新的东西无论如何谢谢你的贡献
        猜你喜欢
        • 2019-05-09
        • 2016-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-26
        • 1970-01-01
        • 2012-05-06
        • 1970-01-01
        相关资源
        最近更新 更多