1

mysql dbからデータを収集して、特定の日数の間アクティブになっていないクライアントにプロモーションメールを送信できるようにする必要がありますが、プロモーションポイントを登録したことがないクライアントのみです。データベースはかなり大きく、50,000を超える顧客があり、ポイントを登録していない顧客のcustomer_idをチェックするクエリは、単独で処理するのに1時間以上かかります。そのため、特定の時間内にログインしていない顧客に絞り込み、それらのcustomer_idのみで検索を実行すると、より高速になると考えました。ただし、2つのクエリを組み合わせようとしたところ、「オペランドには1つの列が含まれている必要があります」というエラーが返され、完全に失敗しました。

クエリで受け取る必要のあるデータを考慮して、達成することさえ可能ですか?

1時間かかる最初のクエリ:

SELECT c.customers_id
FROM customers c 
LEFT JOIN codes_redeem_history pc 
ON pc.customer_id=c.customers_id
WHERE pc.customer_id IS NULL

指定された時間内の顧客に対する2番目のクエリ:

SELECT ci.customers_info_date_of_last_logon, ci.customers_info_id, c.customers_email_address, c.customers_lastname, c.customers_firstname 
FROM customers c, customers_info ci 
WHERE c.customers_id = ci.customers_info_id 
GROUP BY c.customers_email_address 
HAVING max(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY) 
ORDER BY c.customers_lastname, c.customers_firstname ASC

どのように試しましたが、それらを組み合わせることができませんでした:

SELECT c.customers_id
FROM customers c 
LEFT JOIN codes_redeem_history pc 
ON pc.customer_id=c.customers_id
WHERE pc.customer_id IS NULL
AND c.customers_id
IN
(Select ci.customers_info_date_of_last_logon, ci.customers_info_id, c.customers_email_address, c.customers_lastname, c.customers_firstname 
FROM customers c, customers_info ci 
WHERE c.customers_id = ci.customers_info_id 
GROUP BY c.customers_email_address 
HAVING max(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY) 
ORDER BY c.customers_lastname, c.customers_firstname ASC)

エラーメッセージから、クエリのIN(SELECT)部分でこのような複雑なクエリを許可しないことがわかりますが、それを再配置する方法、またはそれが実行可能であるかどうかについては迷っています。

SQL Gurusからのアドバイスはありますか?

ありがとう

要件を少し変更した後、これについてもう少し助けを借りて行うことができます。

以前の回答に加えて、30日に固定するのではなく、期間を選択できるようにクエリを少し変更しようとしました。HAVING MAX(ci.customers_info_date_of_last_logon)>='"。$ndate。"'を使用しました。$ndateは必要な日付を保持する変数です。日付が30DAYSと同じではないため、明らかに機能しませんでした。HAVINGMAXの代わりにWHERE条件を使用できないようです。解決策はありますか?

4

1 に答える 1

2

最初のクエリの完了に時間がかかりすぎる理由は、ほぼ確実です。列の関係を定義するインデックスがないため、次の行を実行してテーブルを変更します。

ALTER TABLE codes_redeem_history ADD INDEX (customer_id);
ALTER TABLE customers ADD INDEX (customers_id);
ALTER TABLE customers_info ADD INDEX (customers_info_id);

完全なクエリ、

SELECT  c.customers_id
FROM    customers c 
        LEFT JOIN codes_redeem_history pc 
        ON pc.customer_id=c.customers_id
        LEFT JOIN
        (
            Select  c.customers_id 
            FROM    customers c 
                    INNER JOIN customers_info ci
                        ON c.customers_id = ci.customers_info_id 
            GROUP   BY c.customers_email_address 
            HAVING  MAX(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY)
        ) d ON c.customers_id = d.customers_id
WHERE   pc.customer_id IS NULL AND 
        d.customers_id IS NOT NULL

更新1

SELECT  c.customers_id
FROM    customers c 
        INNER JOIN customers_info ci
            ON c.customers_id = ci.customers_info_id 
        LEFT JOIN codes_redeem_history pc 
            ON c.customers_id = pc.customer_id
WHERE   pc.customer_id IS NULL
GROUP   BY c.customers_email_address 
HAVING  MAX(ci.customers_info_date_of_last_logon) <= subdate(now(),INTERVAL 30 DAY)
于 2013-03-08T00:44:41.903 に答える