Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多连接的MySQL查询_Mysql_Entity Attribute Value - Fatal编程技术网

多连接的MySQL查询

多连接的MySQL查询,mysql,entity-attribute-value,Mysql,Entity Attribute Value,我有很多连接的查询,我正在搜索它的优化。 它是关于计算机的: 例如,我有: 联想8gbRAM 1TB核心i5 IP等(品牌名称后的所有这些都是属性) 我有一个配置,我想将8gbRAM属性更改为16gbRAM,我必须搜索具有所有这些属性和16gbRAM的其他项 两张表: **st_item** - id - name ... **st_item_specification_attribute** - id - st_item_id - attribute_id - attribute_value

我有很多连接的查询,我正在搜索它的优化。 它是关于计算机的: 例如,我有: 联想8gbRAM 1TB核心i5 IP等(品牌名称后的所有这些都是属性) 我有一个配置,我想将8gbRAM属性更改为16gbRAM,我必须搜索具有所有这些属性和16gbRAM的其他项

两张表:

**st_item**
- id
- name
...

**st_item_specification_attribute**
- id
- st_item_id
- attribute_id
- attribute_value_id
...
我的问题是我的物品有15个属性。当我使用较少的属性数进行测试时,我使用了这种查询结构,它可以工作,但现在系统有85k个项目和超过1kk个项目属性 以下是查询:

SELECT `st_item`.id FROM `st_item` 
LEFT JOIN `st_item_specification_attribute` `sisa_36590` ON st_item.id = sisa_36590.item_id AND sisa_36590.attribute_id = 365 
LEFT JOIN `st_item_specification_attribute` `sisa_367910` ON st_item.id = sisa_367910.item_id AND sisa_367910.attribute_id = 367 
LEFT JOIN `st_item_specification_attribute` `sisa_374641` ON st_item.id = sisa_374641.item_id AND sisa_374641.attribute_id = 374 
LEFT JOIN `st_item_specification_attribute` `sisa_378366` ON st_item.id = sisa_378366.item_id AND sisa_378366.attribute_id = 378 
LEFT JOIN `st_item_specification_attribute` `sisa_382500` ON st_item.id = sisa_382500.item_id AND sisa_382500.attribute_id = 382 
LEFT JOIN `st_item_specification_attribute` `sisa_372134` ON st_item.id = sisa_372134.item_id AND sisa_372134.attribute_id = 372 
LEFT JOIN `st_item_specification_attribute` `sisa_41268` ON st_item.id = sisa_41268.item_id AND sisa_41268.attribute_id = 412 
LEFT JOIN `st_item_specification_attribute` `sisa_413368` ON st_item.id = sisa_413368.item_id AND sisa_413368.attribute_id = 413 
LEFT JOIN `st_item_specification_attribute` `sisa_414929` ON st_item.id = sisa_414929.item_id AND sisa_414929.attribute_id = 414 
LEFT JOIN `st_item_specification_attribute` `sisa_418496` ON st_item.id = sisa_418496.item_id AND sisa_418496.attribute_id = 418 
LEFT JOIN `st_item_specification_attribute` `sisa_385748` ON st_item.id = sisa_385748.item_id AND sisa_385748.attribute_id = 385 
LEFT JOIN `st_item_specification_attribute` `sisa_36625` ON st_item.id = sisa_36625.item_id AND sisa_36625.attribute_id = 366 
LEFT JOIN `st_item_specification_attribute` `sisa_366355` ON st_item.id = sisa_366355.item_id AND sisa_366355.attribute_id = 366 
LEFT JOIN `st_item_specification_attribute` `sisa_366816` ON st_item.id = sisa_366816.item_id AND sisa_366816.attribute_id = 366 
LEFT JOIN `st_item_specification_attribute` `sisa_366370` ON st_item.id = sisa_366370.item_id AND sisa_366370.attribute_id = 366 
WHERE (`parent_id`=1032) AND 
(sisa_36590.attribute_value_id = 2230) AND 
(sisa_367910.attribute_value_id = 2451) AND 
(sisa_374641.attribute_value_id = 3793) AND 
(sisa_378366.attribute_value_id = 2955) AND 
(sisa_382500.attribute_value_id = 3879) AND 
(sisa_372134.attribute_value_id = 2780) AND 
(sisa_41268.attribute_value_id = 3363) AND 
(sisa_413368.attribute_value_id = 3373) AND 
(sisa_414929.attribute_value_id = 3378) AND 
(sisa_418496.attribute_value_id = 3844) AND 
(sisa_385748.attribute_value_id = 3036) AND 
(sisa_36625.attribute_value_id = 2315) AND 
(sisa_366355.attribute_value_id = 2408) AND 
(sisa_366816.attribute_value_id = 2412) AND 
(sisa_366370.attribute_value_id = 2420)

查询必须比较特定的对
attribute\u id=>attribute\u value\u id
,这就是我的“ON子句”与
item\u id
attribute\u id
以及特定的
别名

可以将
WHERE
条件移动到
ON
条件中的原因 并将
左连接
更改为
内连接

SELECT `st_item`.id FROM `st_item` 
JOIN `st_item_specification_attribute` `sisa_36590` 
ON st_item.id = sisa_36590.item_id AND sisa_36590.attribute_id = 365
  AND sisa_36590.attribute_value_id = 2230 
JOIN `st_item_specification_attribute` `sisa_367910`
ON st_item.id = sisa_367910.item_id AND sisa_367910.attribute_id = 367 
 AND sisa_367910.attribute_value_id = 2451 
...
WHERE `parent_id`=1032
第二种方法
您可以使用聚合:

select i.id
from st_item i join
     st_item_specification_attribute sisa
     ON sisa.item_id = i.item_id
where i.parent_id = 1032 and
      (sisa.attribute_id, attribute_value_id) in ( (365, 2230), (367, 2451), . . .)
group by i.id
having count(*) = 15;

我无法预测性能,但我认为您可以从所有连接中选择subselect

(我假定每个项目的属性id和属性值id对是唯一的)


对此,我将使用联合所有的方法。它很容易修改,阅读起来也很简单。性能也应该相当好:

--A CTE so you only have to change parent_id in one place
--I believe not all mysql versions support this, though
--You could of course just select the parent_id in de UNION ALL and 
--   use a single WHERE in the outer query. 
WITH st_item_id AS
(
    SELECT  id
    ,       attribute_id
    ,       attribute_value_id
    FROM    st_item
    WHERE   parent_id = 1032
)

SELECT  UA.id
FROM    (
            SELECT  st_item.id 
            FROM    st_item_id 
            INNER JOIN st_item_specification_attribute sisa_36590 
                    ON st_item_id.id = sisa_36590.item_id 
                    AND sisa_36590.attribute_id = 365 
                    AND sisa_36590.attribute_value_id = 2230

            UNION ALL 

            SELECT  st_item.id 
            FROM    st_item_id 
            INNER JOIN st_item_specification_attribute sisa_367910 
                    ON st_item_id.id = sisa_367910.item_id 
                    AND sisa_367910.attribute_id = 367 
                    AND sisa_367910.attribute_value_id = 2451
        ) UA

由于where子句,所有这些左连接都变成了内部连接。我不能说这是不是你想要的。你必须把那些条件从
WHERE
子句移到
ON
子句。EAV schema design==恶心。你建议如何更改结构?我有一个表“st\u item\u specification\u attribute”,其中存储了所有的item属性,sisa是别名。但有一个特性是,一个属性\u id具有特定的值\u id,但最终它与@Alex第二种方法完全相同(取决于优化器)
SELECT `st_item`.id FROM `st_item` 
WHERE (`parent_id`=1032) AND 
  15 = (SELECT COUNT(*) FROM st_item_specification_attribute attr
         WHERE `st_item`.id = attr.item_id 
           AND (  attribute_id = 365 AND attribute_value_id = 2230 OR
                  ...
               )

    
--A CTE so you only have to change parent_id in one place
--I believe not all mysql versions support this, though
--You could of course just select the parent_id in de UNION ALL and 
--   use a single WHERE in the outer query. 
WITH st_item_id AS
(
    SELECT  id
    ,       attribute_id
    ,       attribute_value_id
    FROM    st_item
    WHERE   parent_id = 1032
)

SELECT  UA.id
FROM    (
            SELECT  st_item.id 
            FROM    st_item_id 
            INNER JOIN st_item_specification_attribute sisa_36590 
                    ON st_item_id.id = sisa_36590.item_id 
                    AND sisa_36590.attribute_id = 365 
                    AND sisa_36590.attribute_value_id = 2230

            UNION ALL 

            SELECT  st_item.id 
            FROM    st_item_id 
            INNER JOIN st_item_specification_attribute sisa_367910 
                    ON st_item_id.id = sisa_367910.item_id 
                    AND sisa_367910.attribute_id = 367 
                    AND sisa_367910.attribute_value_id = 2451
        ) UA