web-dev-qa-db-ja.com

2つのテーブルの比較行で異なるデータをフェッチする方法

私のデータベースには2つのテーブルがあり、1つはユーザー情報が格納されるuser_appテーブルで、テーブルは次のとおりです。

+--------------+--------------+------+-----+-------------------+-----------------------------+
| Field        | Type         | Null | Key | Default           | Extra                       |
+--------------+--------------+------+-----+-------------------+-----------------------------+
| id           | int(11)      | NO   | PRI | NULL              | auto_increment              |
| apikey       | varchar(32)  | NO   |     | NULL              |                             |
| app_id       | varchar(16)  | NO   |     | NULL              |                             |
| appidt       | varchar(100) | NO   |     | NULL              |                             |
| imei_num     | varchar(32)  | NO   | MUL | NULL              |                             |
| app_version  | varchar(20)  | NO   |     | NULL              |                             |
| package_name | varchar(100) | NO   | MUL | NULL              |                             |
| stamp        | timestamp    | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| sdk_version  | float        | NO   |     | NULL              |                             |
+--------------+--------------+------+-----+-------------------+-----------------------------+

他のテーブルは、ユーザーの広告を取得するための広告のテーブルであり、テーブル名のクリエイティブは次のように表示されます。

+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| campaign_id  | tinyint(4)   | NO   |     | NULL    |                |
| status       | tinyint(4)   | NO   |     | NULL    |                |
| type         | varchar(20)  | NO   |     | NULL    |                |
| title        | varchar(40)  | NO   |     | NULL    |                |
| description  | varchar(100) | NO   |     | NULL    |                |
| iconlink     | text         | NO   |     | NULL    |                |
| marketlink   | text         | NO   |     | NULL    |                |
| app_id       | varchar(16)  | YES  |     | NULL    |                |
| package_name | varchar(200) | YES  | MUL | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+

今、私はすべてのユーザー情報をphpスクリプトを介してser_appテーブルで、ユーザーアプリケーションを識別するパッケージ名とともに取得します。一方、creativeテーブルでは、ユーザーに送信される広告をいくつか作成しています。パッケージ名もここで定義します。

ここでは、package_nameに基づいてユーザーアプリケーションをチェックしています。package_nameがクリエイティブテーブルでuser_appと一致する場合、他の広告を取得してユーザーに送信します。このクエリは完了です。

SELECT ua.package_name, c.id as cid, c.title, c.description, c.iconlink, c.marketlink
FROM `user_app` AS ua INNER JOIN `creative` AS c ON ua.package_name <> c.package_name
where ua.imei_num = '30c899b5c0f29dbc95418c4173f6f745'
and c.package_name in (12,13) group by `package_name`

問題は、ユーザーが5つ以上のアプリを持っている場合、アプリごとに異なる広告を取得することですが、このクエリを使用すると、ユーザーアプリとは異なる異なる1つの広告のみを取得できますが、ユーザーがすでに4つのアプリ広告を持っている場合私は彼に別の広告を送る必要があります。

別のステートメントは、このクエリはサーバー上でスムーズに実行されますが、1〜10秒かかるmysql-slowクエリのようにログに記録されることがあるので、パフォーマンスのためにこのクエリを最適化する必要があります。

説明が不完全な場合は申し訳ありませんが、最善を尽くします。

RolandoMySQLDBA:このクエリをもう一度見て、この問題をできるだけ早く解決してください。どんな助けも私にとって非常に素晴らしいことです。

3
Shashank

これが元のクエリです

SELECT ua.package_name, c.id as cid, c.title, c.description, c.iconlink, c.marketlink
FROM `user_app` AS ua INNER JOIN `creative` AS c
ON ua.package_name <> c.package_name
where ua.imei_num = '30c899b5c0f29dbc95418c4173f6f745'
and c.package_name in (12,13)
group by `package_name`

JOINを実行する前に、クエリをリファクタリングして必要な行を取得することをお勧めします

SELECT ua.package_name, c.id as cid, c.title, c.description, c.iconlink, c.marketlink
FROM
(
    SELECT package_name FROM `user_app`
    WHERE imei_num = '30c899b5c0f29dbc95418c4173f6f745'
) AS ua INNER JOIN
(
    SELECT * FROM `creative`
    WHERE c.package_name in (12,13)
) AS c
ON ua.package_name <> c.package_name
group by ua.package_name;

試してみる !!!

1
RolandoMySQLDBA