mysql 在基于几个where子句的规范化表中查找公共ID(值)

rlcwz9us  于 2023-04-19  发布在  Mysql
关注(0)|答案(3)|浏览(97)

我有一个电子商务网站的MYSQL表(offer_properties):

+----------+-------------+---------+
| offer_id | pkey        | pvalue  |
+----------+-------------+---------+
|       63 | shoesize    | shoe_47 |
|       63 | sport       | walking |
|       63 | color       | multi   |
|       12 | color       | multi   |
|       12 | shoesize    | size_48 |
|       12 | shoesize    | size_47 |
|       12 | shoesize    | size_46 |
|       12 | sneakertype | comfort |
|       12 | sport       | running |
+----------+-------------+---------+

什么是最简单的方法来找到报价在哪里

shoesize = size_48 AND sport = running

我可以做到

select offer_id from offer_properties where (pkey = "sport" and pvalue = "running") and offer_id IN (select offer_id from offer_properties where (pkey = "shoesize" and pvalue = "size_48"));

然而,这种递归方法确实很困难,因为可能会有各种属性匹配请求。此外,我还有其他需要JOIN的表,查询变得非常复杂。我有一个表保存值(价格,描述等),另一个规范化的表保存报价标签。
LEFT JOIN找到提供匹配某些标签与某些属性和某些值.然而,事情变得相当复杂非常quickly.
对于这样的场景,你会有什么指导?我应该使用Promises的简单查询,并使用应用程序逻辑来逐步过滤事物吗?
非常感谢

xqkwcwgp

xqkwcwgp1#

您可以使用conditional aggregation来避免自连接。

select offer_id
from (
  select offer_id, 
    sum(case when pkey = 'shoesize' and pvalue = 'size_48' then 1 else 0 end) cond1, 
    sum(case when pkey = 'sport' and pvalue = 'running' then 1 else 0 end) cond2
  from offer_properties
  group by offer_id
  )z
where cond1> 0 and cond2> 0;
offer_id
十二岁

View on DB Fiddle

vsikbqxv

vsikbqxv2#

你可以使用非常简单的self join:

select offer_id
from offer_properties o1
where pkey = "sport"
  and pvalue = "running"
  and exists (
        select 1
        from offer_properties o2
        where o2.offer_id = o1.offer_id
        and o2.pkey = "shoesize"
        and o2.pvalue = "size_48"
        );

或者你可以使用EXIST。它与你当前的查询非常相似。

select offer_id
from offer_properties o1
join offer_properties o2
on (o2.offer_id = o1.offer_id
        and o2.pkey = "shoesize"
        and o2.pvalue = "size_48")
where pkey = "sport"
  and pvalue = "running";

这两种解决方案都需要额外的构造,但对于当前的模型,我相信您没有机会避免它。
另一方面,我认为exists(作为您当前的查询)可以写在一行中,并且不应该使您的查询变得混乱。

knsnq2tg

knsnq2tg3#

不需要连接,也不需要子查询。我们可以使用having子句对聚合进行直接过滤:

select offer_id
from offer_properties
group by offer_id
having max(pkey = 'shoesize' and pvalue = 'size_48') = 1
   and max(pkey = 'sport'    and pvalue = 'running') = 1

相关问题