@rownum没有按预期递增(每组选择n)

时间:2013-01-20 00:47:12

标签: mysql sql

我期待的是tmp.rank为每个1-10增加userid,然后转到下一个userid,但我得到的只是它留在{对于每条记录{1}},因此不会限制每110个项目。

任何想法我做错了,很可能是一些简单明了的事情,或者更有可能以一种不打算的方式使用SQL。

userid

4 个答案:

答案 0 :(得分:1)

我将在这里猜测问题是什么。

您正在组合两种类型的连接语法,这可能会导致您的问题。

您在表格之间使用了JOIN和逗号。您在JOIN和用户变量之间使用user_table,然后在其余表之间使用逗号。

 FROM user_table AS ut JOIN (SELECT @rownum := NULL, @prev := 0) AS r ,
   qa_posts AS qp,
   qa_categories AS qc,
   expatsblog_country AS cc

虽然您的WHERE子句包含大多数表要加入的列。看起来您没有表expatsblog_country的连接条件。当您连接表时,您应该使用一种语法而不是混合它们。

我会建议类似的东西。我没有看到expatsblog_country表的任何连接条件,因此我使用CROSS JOIN将这些表连接到其他表的子查询。如果您有一列要将expatsblog_country加入其他任何列,请将该查询移到子查询中:

SELECT DISTINCT tmp.title,
    tmp.content,
    tmp.postid,
    tmp.userid,
    tmp.screenname,
    tmp.email
FROM
(
  SELECT src.title,
    src.content,
    src.postid,
    src.userid,
    src.screenname,
    src.email,
    src.created,
    @rownum := IF( @prev = src.userid, @rownum+1, 1 ) AS rank,
    @prev := src.userid 
  FROM
  (
    select ut.userid,
      ut.screenname,
      ut.email,
      qp.title,
      qp.content,
      qp.postid,
      qp.created
    from user_table AS ut
    join qa_categories AS qc
      on LOWER(ut.country_of_expat) = LOWER(qc.title)
    join qa_posts AS qp
      on qc.categoryid = qp.categoryid
    where ut.setting_notifications IN (3)
      and ut.valid=1
      and ut.confirm_email = 1
      and qp.type='Q'
      and DATE(qp.created)>=DATE_SUB(NOW(), INTERVAL 24 HOUR)  
  ) src
  CROSS JOIN 
  (
    SELECT @rownum := 0, @prev := 0
  ) AS r
  CROSS JOIN expatsblog_country AS cc
  ORDER BY src.userid, src.created ASC
) AS tmp
WHERE tmp.rank < 10 
ORDER BY tmp.userid, tmp.created ASC

答案 1 :(得分:1)

我过去做过很多查询,特别是回复有关MySQL和@变量的帖子。我遇到的一个问题是应用于行时数据的返回顺序。

你的原始查询DID在最里面的查询中有一个顺序,但是我遇到过@variable赋值并不真正尊重它的时候,并且重置了计数器,因为它转到其他一些(在这种情况下)用户,然后稍后,遇到第一个记录,并将计数器重置为一个,即使它稍后发生。

接下来,您将DISTINCT应用到最后。我会尝试将DISTINCT拉到最里面,这样你就不会得到一些关键的,同一个用户的10条记录,最终只返回2条记录。

那就是说,我会根据下面的内容调整查询。最内层的只是在你想要的列上抓取DISTINCT,然后应用@variable赋值。

SELECT DISTINCT 
      tmp.title,
      tmp.content,
      tmp.postid,
      tmp.userid,
      tmp.screenname,
      tmp.email,
      @rownum := IF( @prev = ut.userid, @rownum+1, 1 ) AS rank,
      @prev := ut.userid 
   FROM
      ( SELECT DISTINCT
              qp.title,
              qp.content,
              qp.postid,
              ut.userid,
              ut.screenname,
              ut.email
           FROM
              user_table AS ut
                 JOIN qa_categories AS qc
                    ON LOWER( ut.country_of_expat ) = LOWER( qc.title )
                    JOIN qa_posts AS qp
                       ON qc.categoryid = qp.categoryid
                      AND qp.type='Q'
                      AND DATE(qp.created)>=DATE_SUB(NOW(), INTERVAL 24 HOUR)
           WHERE
                  ut.setting_notifications = 3
              AND ut.valid = 1
              AND ut.confirm_email = 1
           ORDER BY 
              ut.userid,
              qp.created ASC ) AS tmp,
      ( SELECT @rownum := NULL, 
               @prev := 0) AS r
   HAVING
      tmp.rank < 10
   ORDER BY 
      tmp.userid

我没有看到任何对“cc”的引用被加入任何可能的地方 导致笛卡尔结果为expatsblog_country中的每个条目提供记录 所以我把它删除了...如果需要的话,把它放在适用的地方并放入JOIN条件。

(删除expatsblog_country AS cc)

此外,我改为HAVING子句而不是WHERE子句,因此这样所有返回的记录都是最终结果集的CONSIDERED。这将确保@rownum在遇到可能的条目时会继续递增,但是会抛出所有大于10的条目。

最后,由于内部表已经由用户预先订购并创建了日期,因此您不需要在外部显式重新排序AGAIN ...也许只是我拥有的UserID。

答案 2 :(得分:1)

尝试更改

  ( SELECT @rownum := NULL, 
           @prev := 0) AS r

这样你就可以将@rownum初始化为0,而将@prev初始化为NULL。

答案 3 :(得分:0)

弄清楚这是什么

  1. expats_country不应该成为查询的一部分
  2. 更重要的是:

    1. qp.created周围的“DATE()”搞乱了这个问题以及查询的实际“最后24小时”部分。删除了这个,很好。