sql如何使用这种语法更轻量级?

时间:2015-10-31 00:46:33

标签: mysql sql

您好我收到此消息:

[The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay]

这个语法:

    SELECT CONCAT(v2.meta_value, ' ', v3.meta_value) AS name,
 a.usr, a.vagtDato, b.timeloen, c.provision, d.kursus, e.trappetur, f.sygedag
FROM $main_table a
LEFT JOIN (SELECT usr, count(vagt_type) as timeloen
FROM $main_table  WHERE vagt_type = 'timeloen'
AND vagtDato between DATE('$start') AND DATE('$end')
GROUP BY usr ) b on b.usr=a.usr

LEFT JOIN (SELECT usr, count(vagt_type) as provision
FROM $main_table  WHERE vagt_type = 'provision'
AND vagtDato between DATE('$start') AND DATE('$end')
GROUP BY usr ) c on c.usr=a.usr

LEFT JOIN (SELECT usr, count(vagt_type) as kursus
FROM $main_table  WHERE vagt_type = 'kursus'
AND vagtDato between DATE('$start') AND DATE('$end')
GROUP BY usr ) d on d.usr=a.usr

LEFT JOIN (SELECT usr, count(vagt_type) as trappetur
FROM $main_table  WHERE vagt_type = 'trappetur'
AND vagtDato between DATE('$start') AND DATE('$end')
GROUP BY usr ) e on e.usr=a.usr

LEFT JOIN (SELECT usr, count(vagt_type) as sygedag
FROM $main_table  WHERE vagt_type = 'sygedag'
AND vagtDato between DATE('$start') AND DATE('$end')
GROUP BY usr ) f on f.usr=a.usr

LEFT JOIN Lausten_usermeta v2 ON a.usr=v2.user_id and v2.meta_key = 'first_name'
LEFT JOIN Lausten_usermeta v3 ON a.usr=v3.user_id and v3.meta_key = 'last_name'

WHERE a.vagtDato between DATE('$start') AND DATE('$end')
GROUP BY a.usr
ORDER BY $orderby $order LIMIT %d OFFSET %d

所以我知道我可以设定更高的限制,但我想避免这种情况!

有没有办法让这种语法更轻量化?

2 个答案:

答案 0 :(得分:0)

您可以对子查询使用条件聚合:

LEFT JOIN (SELECT usr,
                  sum(vagt_type = 'timeloen') as timeloen,
                  sum(vagt_type = 'provision') as provision,
                  . . .
           FROM $main_table 
           WHERE vagtDato between DATE('$start') AND DATE('$end')
           GROUP BY usr
          ) b
          on b.usr = a.usr

这将只用一个替换所有子查询。

答案 1 :(得分:0)

在我看来,你正在使用多个Entity-Attribute-Value tables,它们很有用,但也是一个巨大的关系噩梦。您可能希望考虑为常用的EAV表创建视图,以使您的生活更轻松。

那就是说,你可以这样做:

SELECT CONCAT(v.meta_value, ' ', v.meta_value) AS NAME
    ,a.usr
    ,a.vagtDato
    ,b.timeloen
    ,b.provision
    ,b.kursus
    ,b.trappetur
    ,b.sygedag
FROM $MAIN_TABLE a
LEFT JOIN (
    SELECT usr
        ,sum(case when vagt_type = 'timeloen'  then 1 else 0 end) as timeloen
        ,sum(case when vagt_type = 'provision' then 1 else 0 end) as provision
        ,sum(case when vagt_type = 'kursus'    then 1 else 0 end) as kursus
        ,sum(case when vagt_type = 'trappetur' then 1 else 0 end) as trappetur
        ,sum(case when vagt_type = 'sygedag'   then 1 else 0 end) as sygedag
    FROM $MAIN_TABLE
    WHERE vagt_type IN ('timeloen','provision','kursus','trappetur','sygedag')
        AND vagtDato BETWEEN DATE ('$start') AND DATE ('$end')
    GROUP BY usr
    ) b
    ON b.usr = a.usr
LEFT JOIN (
    SELECT user_id
        ,max(case when meta_key = 'first_name' then meta_value else null end) as first_name
        ,max(case when meta_key = 'last_name'  then meta_value else null end) as last_name
    FROM Lausten_usermeta
    GROUP BY user_id
    ) v
    ON v.user_id = a.usr
WHERE a.vagtDato BETWEEN DATE ('$start') AND DATE ('$end')
GROUP BY a.usr
ORDER BY $ORDERBY $ORDER LIMIT %d OFFSET %d

除此之外,几乎不可能分辨出您可以做什么,因为很难说出您的数据实际上是什么样的(特别是您的主要密钥是什么)以及您实际需要的结果。