根据最新日期选择具有多个联接的行


8

我有此查询(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但是我无法理解。

我还在这里这里这里尝试过方法 ,但是我无法使拥有最新活动的人正确。

MySQL版本:5.5.16。company表大约有1mill行,而action表则是70K(正在增长)。在这里,性能对我很重要。

如何解决呢?


2
看到这个问题:MySQL优化查询而不是MAX(Marks)per TaskID,而是要MAX(ActivityDate)per Company。)如果有一个表或一个联接,则没有太大区别。
ypercubeᵀᴹ

Answers:


7

您的查询可以简化为:

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)

SQL提琴


1
这比较简单,每100行似乎比我的答案快0.3秒。
stiq 2014年

2

在尝试了不同的答案后,我开始使用它了,但发现安装起来很慢。

ypercube为我提供了一个答案,该答案指向有关MySQL如何将结果分组的其他类似问题。这使我进入了这个资源,我终于了解了发生了什么。

结果是这样的查询:

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%'

这是正在工作的查询的摆弄


1

您需要将用户,操作和状态表移动到子查询中,如下所示:

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

SQL小提琴

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.