优化这个疯狂的多表连接查询

时间:2013-01-31 15:45:51

标签: mysql join

我们有4个表关系,2个主表 - “资产”和“产品”,通过表 - “assets_products”和产品/价格关系。以下是仅包含相关字段的表格的要点:

资产

+----------------------------------+--------------+------+-----+---------------------+-----------------------------+
| Field                            | Type         | Null | Key | Default             | Extra                       |
+----------------------------------+--------------+------+-----+---------------------+-----------------------------+
| id                               | int(11)      | NO   | PRI | NULL                | auto_increment              |
| in_store                         | tinyint(4)   | YES  |     | 0                   |                             |
| isbn                             | varchar(32)  | YES  | MUL | NULL                |                             |
+----------------------------------+--------------+------+-----+---------------------+-----------------------------+

产品;

+------------------------+---------------+------+-----+---------------------+-----------------------------+
| Field                  | Type          | Null | Key | Default             | Extra                       |
+------------------------+---------------+------+-----+---------------------+-----------------------------+
| id                     | int(11)       | NO   | PRI | NULL                | auto_increment              |
| sku                    | varchar(40)   | YES  | UNI | NULL                |                             |
| type                   | varchar(30)   | YES  |     | NULL                |                             |
| asset_id               | int(11)       | YES  |     | NULL                |                             |
| in_store               | tinyint(4)    | NO   | MUL | 0                   |                             |
| parent_id              | int(11)       | YES  | MUL | NULL                |                             |
+------------------------+---------------+------+-----+---------------------+-----------------------------+

assets_products;

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| asset_id   | int(11)  | NO   | MUL | 0       |                |
| product_id | int(11)  | NO   | MUL | 0       |                |
+------------+----------+------+-----+---------+----------------+

价格;

+----------------------+--------------+------+-----+---------+----------------+
| Field                | Type         | Null | Key | Default | Extra          |
+----------------------+--------------+------+-----+---------+----------------+
| price                | decimal(8,2) | NO   |     | 0.00    |                |
| currency             | varchar(3)   | NO   | MUL | USD     |                |
| effective_begin_date | datetime     | YES  |     | NULL    |                |
| effective_end_date   | datetime     | YES  |     | NULL    |                |
| priceable_id         | int(11)      | YES  | MUL | NULL    |                |
| priceable_type       | varchar(255) | YES  | MUL | NULL    |                |
+----------------------+--------------+------+-----+---------+----------------+

第一个关系称为单一关系,这里是关系的摘要:

  1. 资产/产品中的一对一资产通过assets_products
  2. 产品类型设置为“单个”,assets.isbn匹配products.sku
  3. 第二种关系称为租赁/演示关系:

    1. 产品类型为“Rental”或“Demo”
    2. 将products.parent_id设置为“父”产品的ID,该产品是单一关系(资产/产品通过assets_products一对一匹配)
    3. 第三种关系称为包

      1. 一个包是以上所有(单打,单打+出租或演示)的集合,他们可以被视为包的“孩子”
      2. 包可以通过assets_products表中与Package的product_id匹配的所有asset_id访问它的“children”。
      3. 每个产品都通过prices.pricable_id = products.id和prices.pricable_type = products.type(包裹或产品)链接到价格表,我们需要显示有效价格的产品

         prices.effective_begin_date <= 'today' AND prices.effective_end_date >= '2020-23-01' 
        

        推动此查询的其他主要标准是Singles有cached_product_in_store = 1且产品有和in_store = 1。

        现在,进退两难。我试图通过asset.title和products.name在一个查询中搜索所有搜索,疯狂看起来像这样:

        SELECT 
            a1.id AS aid, p1.id AS pid, p1.type, p1.in_store as pin_store, a1.cached_product_in_store, p1.parent_id, a1.title, p1.name
        FROM assets a1
        INNER JOIN (assets_products, products p1, prices) ON
             p1.id = assets_products.product_id AND
             a1.id = assets_products.asset_id AND
             p1.id = prices.priceable_id AND
             prices.effective_begin_date <= '2013-23-01' AND
             prices.effective_end_date >= '2020-23-01' AND
             prices.priceable_type IN ('Product', 'Package') AND
             prices.currency = 'USD'
        WHERE 
            (CASE
                WHEN ((p1.type='Rental' OR p1.type='Demo') AND p1.parent_id IS NOT NULL) THEN (p1.in_store=(SELECT in_store FROM products p2 WHERE p1.parent_id=p2.id AND p2.in_store=1)) AND
                    (LOWER(p1.name) LIKE '%Global%' AND LOWER(p1.name) LIKE '%History%' AND LOWER(p1.name) LIKE '%&%' AND LOWER(p1.name) LIKE '%Geography%')
                WHEN (p1.type='Package') THEN (p1.in_store=1) AND
                    (LOWER(p1.name) LIKE '%Global%' AND LOWER(p1.name) LIKE '%History%' AND LOWER(p1.name) LIKE '%&%' AND LOWER(p1.name) LIKE '%Geography%')
                WHEN (p1.type='Single') THEN (a1.cached_product_in_store=1) AND
                    (LOWER(a1.title) LIKE '%Global%' AND LOWER(a1.title) LIKE '%History%' AND LOWER(a1.title) LIKE '%&%' AND LOWER(a1.title) LIKE '%Geography%')
            END)
        GROUP BY p1.id
        

        它很接近,但GROUP BY p1.id使查询的执行时间加倍。

        有什么想法吗?

0 个答案:

没有答案