私はこのクエリを持っています( SQLFiddle ):
_SELECT
c.name,
a.user_id,
a.status_id,
a.title,
a.rtime,
u.user_name,
s.status_name
FROM company c
LEFT JOIN action a ON a.company_id=c.id
LEFT JOIN user u ON u.id=a.user_id
LEFT JOIN status s ON s.id=a.status_id
WHERE u.user_name='Morgan'
-- WHERE c.name='Fiddle'
GROUP BY c.id
HAVING a.rtime IS NULL OR a.rtime = (
SELECT max(rtime)
FROM action a2
WHERE deleted IS NULL
AND a2.company_id = c.id
)
_
問題1
すべての会社をリストして、ユーザーと会社が最後に会社に対してアクションを行ったステータスを表示したいと思います。同時に、何も行われていない会社を表示します。
問題2
また、名前でユーザーを検索できるようにする必要があります。これにより、このユーザーが最後に活動した企業をすべて選択できます。クエリはフォームから作成されるため、変数を挿入できます。
現在のところ、データベースSCHEMAを変更することはできませんが、将来の移行のためのアドバイスはかなり役に立ちます。
INNER JOIN ( SELECT.. ) t ON
と一緒にバインドしてみましたが、頭がよくありません。
here 、 here 、および here のメソッドも試しましたが、最新のアクティビティを持つ人を正しく取得できません。
MySQLバージョン:5.5.16。会社のテーブルの行数は約1ミルで、アクションテーブルは70Kになり、増加しています。ここではパフォーマンスが重要です。
これをどのように解決できますか?
クエリは次のように簡略化できます。
_SELECT
c.id,
c.name,
a.rtime,
s.status_name,
u.user_name
FROM company c
LEFT JOIN
( SELECT
company_id,
MAX(rtime) AS maxdate
FROM action
WHERE deleted IS NULL
GROUP BY company_id
) AS x ON x.company_id = c.id
LEFT JOIN action a ON a.deleted IS NULL
AND a.company_id = x.company_id
AND a.rtime = x.maxdate
LEFT JOIN user u ON u.id = a.user_id
LEFT JOIN status s ON s.id = a.status_id
WHERE
c.name LIKE 'Company%' ;
_
_(deleted, company_id, rtime)
_のインデックスは、派生テーブルのサブクエリを効率的にします。結合に使用される列とCompany (name)
にすでにインデックスがあると思います。
さまざまな答えを試してみましたが、うまくいきましたが、設定が遅いことがわかりました。
ypercubeは、MySQLが結果をグループ化する方法についての他の同様の質問を指摘する答えを私に示しました。これは私を this resource に導き、そこで何が起こっているのかを最終的に理解しました。
結果は次のようなクエリになります。
SELECT
c.id,
c.name,
a.rtime,
s.status_name,
u.user_name
FROM company c
LEFT JOIN (
SELECT
a.company_id,
a.rtime,
a.user_id,
a.status_id
FROM
(
SELECT company_id,
MAX(rtime) as maxdate
FROM action
WHERE deleted IS NULL
GROUP BY company_id
) as x
LEFT JOIN action a ON a.rtime=x.maxdate AND a.company_id=x.company_id
) as a ON a.company_id=c.id
LEFT JOIN user u ON u.id=a.user_id
LEFT JOIN status s ON s.id=a.status_id
WHERE (1)
-- Search by user
-- AND u.user_name LIKE 'Johnny'
-- Seach by company name
AND c.name LIKE 'Company%'
次のように、ユーザー、アクション、ステータスのテーブルをサブクエリに移動する必要があります。
SELECT
c.name,
a.user_id,
a.status_id,
a.title,
a.max_rtime,
a.user_name,
a.status_name
FROM company c
LEFT JOIN
(select company_id, user_id,
max(rtime) max_rtime,
title, status_id, s.status_name,
u.user_name
from action INNER JOIN
status s ON s.id=action.status_id
INNER JOIN user u ON u.id=action.user_id
where action.deleted IS NULL
group by company_id, user_id, status_id, s.status_name, title, u.user_name
) a ON a.company_id=c.id AND a.user_name='Morgan'
GROUP BY c.id