4

次の 3 つの MySQL テーブルについて考えてみましょう。

tweets                        urls                    tweets_urls
---------------------------   ---------------------   ----------------
tweet_id text          spam   url_id  host     spam   tweet_id  url_id
---------------------------   ---------------------   ----------------
   1     I love cnn.com  0      16    cnn.com    0        1       16
   2     fox.com is fuk  0      17    fox.com    1        2       17
   3     love me!        0                                4       16
   4     blah cnn.com    0
   5     nice fox.com    0

tweets_urls に従って tweets.spam を更新したいのですが、クエリの出力は次のようになります。

tweets
---------------------------
tweet_id text          spam
---------------------------
   1     I love cnn.com  0  <-- tweets_urls tells me tweet_id 1 has url_id 16
   2     fox.com is fuk  1      in it, and the urls-table tells me that url 16
   3     love me!        0      is not spam (spam = 0)
   4     blah cnn.com    0
   5     nice fox.com    1

私は自分自身を明確にしていることを願っています。私はそれをいじっていて、今このようなものを持っています。正しくないことはわかっていますが、最初からやり直す方法がわかりません。あなたは?

UPDATE tweets SET spam = (
  SELECT spam FROM urls
  LEFT JOIN tweets_urls
  WHERE urls.url_id = tweets_urls.url_id
)

どんな助けでも大歓迎です:-)

4

2 に答える 2

3

tweets副選択をテーブルとON結合の句に関連付けるのを忘れました。

UPDATE tweets SET spam = (
  SELECT spam FROM urls
  LEFT JOIN tweets_urls ON urls.url_id = tweets_urls.url_id
  WHERE tweets_urls.tweet_id = tweets.tweet_id
)

また、次の場合に何をすべきかを定義していません。

  • tweets_urlstweet_idのエントリはありません
  • tweets_urlstweet_idには複数のエントリがあります

最後に、補足として、このように更新してもよろしいです? ビューまたはストアド プロシージャを使用して生成したいもののように聞こえますが、テーブルにデータを入力するために今追加しただけのテーブルでurlsあり、後でドロップする場合を除きます。tweets_urlstweets

于 2012-07-10T18:33:41.097 に答える
1

指定されたデータに対して、このクエリは結果セットを返します...

SELECT t.tweet_id
     , t.text
     , IFNULL(s.spam,t.spam) AS spam
  FROM tweets t
  LEFT
  JOIN ( SELECT tu.tweet_id, MAX(u.spam) AS spam
           FROM tweets_urls tu
           JOIN urls u ON u.url_id = tu.url_id
          WHERE u.spam = 1
          GROUP BY tu.tweet_id
       ) s
    ON s.tweet_id = t.tweet_id

ただし、特定の tweet_id に対して tweets_url に複数の行がある場合、または一致する URL がない場合などに何をすべきかについて、いくつかの仮定を立てました。

ツイートが「spam=1」とマークされた URL に関連していることが判明した場合は常に「spam=1」とマークする必要がある場合は、ツイートを「spam=1」とマークする必要があります。 0"...

これにより、そのルールに基づいて、ツイートのすべての行にスパム列が設定されます...

UPDATE tweets t
  LEFT
  JOIN ( SELECT tu.tweet_id, MAX(u.spam) AS spam
           FROM tweets_urls tu
           JOIN urls u ON u.url_id = tu.url_id
          WHERE u.spam = 1
          GROUP BY tu.tweet_id
       ) s
    ON s.tweet_id = t.tweet_id
   SET t.spam = IFNULL(s.spam,0)

スパム列をそのままにしておきたい場合 (設定されている値のままにしておく)、値が現在 0 に設定されている行のみを更新したい場合は、「一致する URL にスパムがある」に従って、値を 1 に設定する必要があります。 =1」、これを行うことができます:

UPDATE tweets t
  JOIN ( SELECT tu.tweet_id
           FROM tweets_urls tu
           JOIN urls u ON u.url_id = tu.url_id
          WHERE u.spam = 1
          GROUP BY tu.tweet_id
       ) s
    ON s.tweet_id = t.tweet_id
   SET t.spam = 1
 WHERE t.spam = 0

tweets テーブルの述語であることに注意してください。現在、spam がゼロに設定されている行のみを更新します。また、urls テーブルから spam 列の値を参照する必要がないことに注意してください。値が 1 であることは既にテスト済みなので、tweets.spam への値の割り当てでリテラル 1 を使用できます。桁。また、(LEFT OUTER JOIN ではなく) INNER JOIN を実行していることにも注意してください。したがって、値 1 が割り当てられる行のみを更新します。


于 2012-07-10T19:08:17.703 に答える