1. 程式人生 > >多對多的屬性對應表如何做按照類別的多屬性匹配搜索

多對多的屬性對應表如何做按照類別的多屬性匹配搜索

engine 自然 inno def lan 連表 creat 進行 針對

電商設計中常用到的屬性對應表需要做按照類別的多屬性匹配功能,舉例建表如下

CREATE TABLE goods_attr (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 自增id,
  `goods_id` int(11) DEFAULT 0 COMMENT 商品id,
  `type` int(11) DEFAULT 0 COMMENT 屬性類型:1:商品類型 2:支持語言 3:支持平臺,
  `value` varchar(50) DEFAULT ‘‘ COMMENT 屬性值,
  PRIMARY KEY
(`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT=商品屬性信息表;
INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (1, 118, 1, 1);
INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (2, 118, 1, 5);
INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES
(3, 118, 1, 8); INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (4, 118, 2, 1); INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (5, 146, 3, 1); INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (6, 146, 1, 1); INSERT
INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (7, 157, 1, 8); INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (8, 157, 1, 5); INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (9, 157, 2, 1); INSERT INTO goods_attr (`id`, `goods_id`, `type`, `value`) VALUES (10, 157, 1, 1);

技術分享

如上所述,goods_id type value組成唯一的一條記錄

比如

首先,118商品擁有三個類型,是一個復合類型商品 有 1 5 8 三種類型

同時,118商品有一個語言 是1類型的語言

同時,118商品有1個平臺 是1類型平臺

146商品就只有一個類型是1,一種平臺是1,而且沒有語言

然後現在前臺或者接口調用處要根據某個屬性進行反查詢得到商品id,最常見的地方是商品的屬性搜索,參考

https://s.taobao.com/list?spm=a217l.8087239.620327.1.729cb1d2ofc3E9&q=%E7%94%B5%E9%A5%AD%E7%85%B2&style=grid&seller_type=taobao

可以看到能夠根據該類別商品的屬性進行搜索

技術分享

比如容量 控制方式 等進行多屬性匹配搜索。

那麽,就需要一個很復雜的復合查詢才行,采用inner join多次連表也是能做到的,不過書寫的SQL就比較復雜,而且很難保證效率。

針對我們的表 假如要查詢 商品類型為5和8的復合類型,而且支持語言為1的商品,該如何查詢呢?

最容易想到的是

select * from goods_attr where ( type=1 and value in (5,8) ) or ( type=2 and value in (1) )

技術分享

但是這樣的查詢條件必然是不正確的,因為 只要符合其中一個條件,那些不相幹的記錄也被查出來了,稍稍改進進行自鏈接

select * from goods_attr as a  left join goods_attr as b on a.goods_id=b.goods_id and (( a.type=1 and a.value in (5,8) ) and ( b.type=2 and b.value in (1) ))

技術分享

這樣的自鏈接看似是正確的,實際上偏離了我們要求的同時滿足復合屬性的記錄存在,value必須有5 而且又有8 而不是in (‘5‘,‘8‘) 所以也是不正確的。

如何得到同時有5又有8呢?只能這樣寫

select a.* from goods_attr as a  inner join goods_attr as b on a.goods_id=b.goods_id and  a.type=1 and a.value=5 and b.value=8

技術分享

這種情況下能查詢出 type=1的情況下既有5 又有8 的屬性。那如何加上查詢type=2的情況下 value=1的屬性條件呢?當然是再連接一次!

select c.goods_id from 
(
        select a.* from goods_attr as a  inner join goods_attr as b on a.goods_id=b.goods_id and   a.type=1 and a.value=5 and b.value=8
) as tmp inner join goods_attr as c on c.goods_id=tmp.goods_id where c.type=2 and c.value=1

技術分享

至此,自鏈接方法講述完畢,如果不想用大量的自鏈接,又該如何做呢?

我想到,可以使用行轉列的方式進行操作,行轉列,借助 group_concat實現

select goods_id,type, group_concat(value) as v from (
  select * from goods_attr  order by goods_id asc,type asc,value asc
) as u where  (type=1 and value in (5,8)) or (type=2 and value in (1))  group by goods_id,type

技術分享

然而這樣查詢出來的結果並沒有自然的排序放入 group_concat中 所以需要強制性指明排序

select goods_id,type, group_concat(value order by goods_id asc,type asc,value asc) as v from goods_attr where (type=1 and value in (5,8)) or (type=2 and value in (1))  group by goods_id,type

這樣就能強制性拿到排序

技術分享

現在得到了屬性的分組,然後我們還要把屬性分類和分組的值再次合並形成一列,和剛剛一樣 再次使用group_concat

select group_concat(type,"-",v) as final,goods_id from 
 (select goods_id,type,v from (
      select goods_id,type, group_concat(value order by goods_id asc,type asc,value asc) as v from goods_attr as u where  (type=1 and value in (5,8)) or (type=2 and value in (1))  group by goods_id,type
 ) as tmp
) as t group by goods_id 

技術分享

很顯然,我們拿到了所有符合的商品屬性的列和商品id,那麽再加一條查詢條件即可或得到我們需要的屬性列表

select goods_id from (
   select group_concat(type,"-",v) as final,goods_id from 
     (select goods_id,type,v from (
          select goods_id,type, group_concat(value order by goods_id asc,type asc,value asc) as v from goods_attr as u where  (type=1 and value in (5,8)) or (type=2 and value in (1))  group by goods_id,type
     ) as tmp
   ) as t group by goods_id 
) as f where final=1-5,8,2-1

技術分享

這樣我們就得到了需要的商品id!!!

因這篇文章探討SQL比較深入,所以這裏加一下版權。

版權所有,轉載需要聲明原文地址 http://www.cnblogs.com/lizhaoyao/p/7199611.html

多對多的屬性對應表如何做按照類別的多屬性匹配搜索