【问题标题】:MySQL query optimization prestashopMySQL 查询优化 prestashop
【发布时间】:2015-08-11 17:42:05
【问题描述】:

我目前正在编写一条 SQL 语句,用于在 Prestashop 设置数据库中获取特定国家/地区的时区。我使用的表格是:

  • ps_timezone:时区(加拿大/大西洋、美洲/阿达克等)
  • ps_country_lang:国家名称(加拿大、美国、法国等)
  • ps_country:国家/地区表(我知道国家,但我想知道它的区域,所以我使用它。
  • ps_zone:区域(美洲、欧洲、亚洲等)

我写了以下查询(id_country =4 是加拿大):

SELECT tz.id_timezone, tz.name FROM ps_timezone tz WHERE tz.name LIKE CONCAT((SELECT cl.name FROM ps_country_lang cl WHERE cl.id_country=4 and cl.id_lang = 1) ,'%') OR tz.name LIKE CONCAT((SELECT CASE WHEN INSTR(z.name, 'Europe') > 0 THEN 'Europe' WHEN INSTR(z.name, 'America') > 0 THEN 'America' ELSE z.name END as zone_name FROM ps_zone z JOIN ps_country c ON z.id_zone = c.id_zone WHERE c.id_country =4), '%') ORDER BY CASE WHEN tz.name LIKE CONCAT((SELECT cl.name FROM ps_country_lang cl WHERE cl.id_country=4 and cl.id_lang = 1) ,'%') THEN 1 ELSE 2 END, tz.name ASC;

查询运行良好,但我希望前辈就优化我的个人进步和文化提出建议。

首先,我使用 LIKE 来验证时区是否以国家名称开头:

tz.name LIKE CONCAT((SELECT cl.name FROM ps_country_lang cl WHERE cl.id_country=4 and cl.id_lang = 1) ,'%')

或区域名称:

tz.name LIKE CONCAT((SELECT CASE WHEN INSTR(z.name, 'Europe') > 0 THEN 'Europe' WHEN INSTR(z.name, 'America') > 0 THEN 'America' ELSE z.name END as zone_name FROM ps_zone z JOIN ps_country c ON z.id_zone = c.id_zone WHERE c.id_country =4), '%')

我怀疑 LIKE 关键字不是性能最高的……提取时区的第一部分并像这样直接比较它会不会更高效:

WHERE LEFT(tz.name, INSTR(tz.name, "/") - 1) = (SELECT cl.name FROM ps_country_lang cl WHERE cl.id_country=4 and cl.id_lang = 1)

其次,我在 ORDER BY 中使用了 SELECT,因此首先显示的是带有国家名称的时区。

ORDER BY CASE WHEN tz.name LIKE CONCAT((SELECT cl.name FROM ps_country_lang cl WHERE cl.id_country=4 and cl.id_lang = 1) ,'%') THEN 1 ELSE 2 END, tz.name ASC

当然,这是美学问题,但我担心性能问题。查询是否只运行一次,因为它使用固定值(在将查询发送到数据库之前我知道国家/地区 ID,并且语言应该始终为 1 表示英语)还是会为每一行运行一次?

此外,我不太喜欢它,因为我在 WHERE 子句和 ORDER BY 子句中都有完全相同的子查询。我不能使用 SELECT 子句中的别名,因为首先执行 WHERE 子句(无论如何它会迫使我无用地返回一行)。

当然,如果我有国家的时区,最好的做法是排除带有大陆名称的时区...

我意识到这些都不是简单的问题,但我认为这些对于许多像我一样认真学习正确编程的大三学生来说都是有趣的问题。

谢谢,

来自蒙特利尔的Jonathan Parent-Lévesque

【问题讨论】:

    标签: mysql select optimization timezone prestashop


    【解决方案1】:

    我将利用 PHP 5.2 中引入的 DateTimeZone PHP 组件来简化此查询,该组件返回给定 ISO 3166-1 国家代码(例如加拿大的“CA”)的时区标识符。

    例子:

    <?php
    
    $country_iso_code = 'CA';
    $timezone = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country_iso_code);
    
    echo $timezone[0]; /* Multiple timezones per country, get the 1st one */
    

    【讨论】:

    • 如果是我自己的编码,我肯定会使用该解决方案,但 prestashop 是一个电子商务平台,开发人员可以在其上添加自定义模块。我从老板的其他软件 (GEM-CAR) 导入数据的个人经验是,数据结构中的轻微更改/遗漏会导致 Prestashop 无法工作(例如,如果您将空字符串作为姓氏)​​。这就是为什么我使用这个复杂的查询来获取 prestashop 包含的时区。但是,我很乐意为我的个人项目考虑该解决方案。谢谢
    • 在 PrestaShop 中,我们构建 ps_timezone MySQL 表的唯一目的是在 config/config.inc.php 中正确设置 date_default_timezone_set() 函数。该表是 DateTimeZone::listIdentifiers() 的纯粹反映,当时不存在并且未链接到 Country 或 Zones。这就是为什么我建议使用 DateTimeZone PHP 类并拥有一个完全独立的代码,除了 PrestaShop 核心。
    猜你喜欢
    • 1970-01-01
    • 2011-01-22
    • 2011-07-07
    • 2018-12-21
    • 2010-12-15
    • 2011-11-04
    相关资源
    最近更新 更多