【问题标题】:A better way to modify this query so the subquery will be more specific?修改此查询以使子查询更具体的更好方法?
【发布时间】:2014-07-31 13:20:12
【问题描述】:

这是我正在使用的当前查询,到目前为止它做得很好:

SELECT   a.*
FROM     ads AS a
WHERE    id = (
   SELECT   id
   FROM     ads AS b
   WHERE    a.zone_name=b.zone_name
      AND   publish_date <= CURDATE() AND expire_date >= CURDATE() AND active = 1
   LIMIT 1
)

它为每个现有区域返回一个广告,然后在按区域对它们进行排序后,在模板中的适当位置显示适当的广告。

现在我们引入了响应式布局,因此这些区域不能始终适合广告的相同尺寸,我希望始终获取适合的最大尺寸。我首先使用 Javascript 读取浏览器分辨率,将其传递回 PHP,然后 PHP 和 MySQL 可以决定适合哪些广告。

但我不知道如何比我在下面提供的解决方案更容易地将该条件放入查询中,我想要一个更好的解决方案。由于不同的区域将在相同的分辨率下适应不同的尺寸,我需要一种方法来指定每个区域的大小,我能想到的唯一方法是逐个获取它们,为每个区域指定所需的大小,然后在他们身上做一个UNION ALL

但这似乎执行起来相当缓慢,我想知道是否有更好的方法可以简化条件并可能删除publish_date 条件的重复,避免UNION,因此(希望)执行得更快?

(SELECT ads.* FROM ads WHERE zone_name = 'b' AND width=468 AND publish_date <= CURDATE() AND expire_date >= CURDATE() AND active = 1 LIMIT 1)
UNION ALL
(SELECT ads.* FROM ads WHERE zone_name = 'a1' AND width=728 AND publish_date <= CURDATE() AND expire_date >= CURDATE() AND active = 1 LIMIT 1)

...

【问题讨论】:

    标签: mysql subquery


    【解决方案1】:

    这是您的查询:

    SELECT   a.*
    FROM     ads a
    WHERE    id = (SELECT   id
                   FROM     ads b
                   WHERE    a.zone_name=b.zone_name AND
                            publish_date <= CURDATE() AND
                            expire_date >= CURDATE() AND
                            active = 1
                  LIMIT 1
                 );
    

    您似乎并不关心您获得了哪个广告(例如获得最新的)。

    索引是一个很好的起点:

    create index idx_ads_4 on ads(zone_name, active, expire_date, publish_date)
    

    这是一个“覆盖索引”,意味着子查询中使用的所有列都使用该索引。

    接下来,如果您有不同的区域大小,则将其放入表格并使用join。完整的查询类似于:

    select a.*
    from (select 'b' as zone_name, 468 as width union all
          select 'a1', 728
         ) ZoneWidths join
         ads a
         on a.zone_name = zonewidths.zone_name and a.width = zonewidths.width
    where id = (SELECT   id
                FROM     ads b
                WHERE    a.zone_name=b.zone_name AND
                         a.width = b.width AND
                         publish_date <= CURDATE() AND
                         expire_date >= CURDATE() AND
                         active = 1
                LIMIT 1
               );
    

    这个查询的相应索引也需要width:

    create index idx_ads_5 on ads(zone_name, width, active, expire_date, publish_date)
    

    【讨论】:

    • 太好了,我刚刚实施了更改,效果很好。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2012-05-16
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    相关资源
    最近更新 更多