2017-01-09 64 views
0
entity 
--- 
id name 
--- 
1 one 
2 two 
3 three 

property 
--- 
id name 
--- 
1 prop1 
2 prop2 
3 prop3 

entity_property 
--- 
entity_id property_id 
--- 
1   1 
1   2 
1   3 
2   1 

我想获得至少有1和2(但可以有更多)属性的实体。选择哪里(1和2)在GROUP_CONCAT()

这是一种解决方法,我不喜欢:

SELECT entity_property.entity_id, 
(GROUP_CONCAT(entity_property.property_id)) as props 
FROM `entity_property` 
JOIN entity 
ON entity_property.entity_id = entity.id 
GROUP BY entity.id 

它返回:

entity_id props 
--- 
1 1,2,3 
2 1 

然后我有服务器的语言爆发,然后排除。


该查询返回所有实体的行:

SELECT entity.id 
FROM entity 
WHERE (1 AND 2) IN 
    (SELECT property_id 
    FROM entity_property 
    LEFT JOIN entity 
    ON entity_property.entity_id = entity.id 
    WHERE entity_property.entity_id = entity.id) 

此查询导致错误:

SELECT entity.id as ent_id 
FROM entity 
WHERE (1 AND 2) IN 
    (SELECT property_id 
    FROM entity_property 
    LEFT JOIN entity 
    ON entity_property.entity_id = entity.id 
    WHERE entity_property.entity_id = ent_id) 
+1

见http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-一个非常简单的sql查询 - 但我不回答包含单词'想'的问题 - 这只是一个规则。 – Strawberry

回答

0

可以使用group byhaving得到实体ID:

SELECT ep.entity_id 
FROM `entity_property` ep 
WHERE ep.property_id IN (1, 2) 
GROUP BY ep.entity_id 
HAVING COUNT(DISTINCT ep.property_id) = 2; 

注:

  • 这不需要entity表。
  • 如果在entity_property中不允许有重复对,则不需要DISTINCT
  • 更多的属性,您需要更改打扰WHEREHAVING(其中“2”是的东西,你想匹配的数量)。
+0

很好,我明白了! – Xitroff

0

您有兴趣从entity那些在entity_property与1或2的值记录的所有记录要做到这一点,你可以只用内部的一个限制因素加入entity_property,例如

SELECT 
    e.* 
FROM entity e 
INNER JOIN entity_property ep1 
    ON ep1.entity_id = e.id 
    AND ep1.property_id = 1 
INNER JOIN entity_property ep2 
    ON ep2.entity_id = e.id 
    AND ep2.property_id = 2 

内部连接确保只有来自entity的记录返回entity_property中的对应行。双连接可以让您确保entity行同时拥有1和2。使用简单连接允许使用索引,例如在entity_property (property_id , entity_id)

0

索引可以找到使用条件有property_ids的ENTITY_ID ATLEAST 1,2有条款,并获得该group_concat。

试试这个:

select entity_id, group_concat(property_id) 
from entity_property 
group by entity_id 
having 
count(distinct 
     case when property_id in (1, 2) 
     then property_id end) = 2;