0

私が期待しているのは、tmp.rankが次のレコードに移動する前に増分1-10することですが、取得しているのは、すべてのレコードに対してオンのままであるため、あたりのアイテム数が制限されないことです。useriduserid110userid

私が間違っていることのアイデア、おそらく単純で明白なもの、または意図しない方法でSQLを使用している可能性が高いもの。

SELECT DISTINCT 
        tmp.title,
        tmp.content,
        tmp.postid,
        tmp.userid,
        tmp.screenname,
        tmp.email
FROM
(
    SELECT
        qp.title,
        qp.content,
        qp.postid,
        ut.userid,
        ut.screenname,
        ut.email,
        qp.created,
        @rownum := IF( @prev = ut.userid, @rownum+1, 1 ) AS rank,
        @prev := ut.userid 
    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
        LOWER(ut.country_of_expat) = LOWER(qc.title)
        AND ut.setting_notifications IN (3)
        AND ut.valid=1
        AND ut.confirm_email = 1
        AND qc.categoryid = qp.categoryid
        AND qp.type='Q'
        AND DATE(qp.created)>=DATE_SUB(NOW(), INTERVAL 24 HOUR)  
    ORDER BY ut.userid,qp.created ASC
) AS tmp
WHERE tmp.rank < 10 
ORDER BY tmp.userid, tmp.created ASC
4

4 に答える 4

1

ここで問題が何であるかを推測します。

2種類の結合構文を組み合わせているため、問題が発生している可能性があります。

JOINテーブル間でaとコンマの両方を使用しています。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。テーブルを結合するときは、1つのタイプの構文を使用し、それらを混在させないでください。

私はこれに似たものを提案します。テーブルの結合条件が表示されなかった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
于 2013-01-20T01:19:40.217 に答える
1

私は過去に多くのクエリを実行しました。特に、MySQLと@変数に関するここでの投稿に応答しています。私が遭遇した問題の1つは、行に適用するときのデータの戻り順序です。

元のクエリDIDには、最も内側のクエリでの順序がありますが、@変数の割り当てが実際にはそれを尊重しておらず、他の(この場合は)ユーザーに渡されるためにカウンターがリセットされる場合があります。後で、最初のレコードにさらに遭遇し、後で発生した場合でもカウンターを1にリセットします。

次に、最後に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を削除)

また、WHERE句の代わりに、HAVING句に変更したため、このようにして、返されたすべてのレコードが最終結果セットとして考慮されます。これにより、@ rownumは、POSSIBLEエントリに遭遇したときに増分し続けますが、10を超えるエントリはすべて破棄されます。

最後に、内側のテーブルはすでにユーザーによって事前に注文されており、日付が作成されているため、外側でもう一度明示的に並べ替える必要はありません...おそらく私が持っているユーザーIDだけです。

于 2013-01-20T02:24:10.043 に答える
1

変更してみてください

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

そのため、@ rownumを0に初期化し、代わりに@prevをNULLに初期化します。

于 2013-01-20T09:30:27.967 に答える
0

これが何であるかを理解した

  1. expats_countryはクエリの一部ではないはずでした

そして更に重要なことに:

  1. qp.createdの周りの「DATE()」はこれを台無しにしていて、クエリの実際の「過去24時間」の部分も混乱させていました。これを削除して、問題ありませんでした。
于 2013-01-20T21:23:45.713 に答える