与各种选择的多对多关系

时间:2015-12-08 20:47:12

标签: php mysql many-to-many

好的,我一直试图为此寻找解决方案,虽然不是很完美,但我有点做了,我觉得可能会有更好的解决方案。

这有点棘手,我有3张桌子 -
购物车 -

id | name
----------
1  | x
.. | ..

cart_items -

cart_id | item_id
------------------
1       | 1
1       | 2
2       | 1
2       | 3

项目 -

id | color | shape | size | ...
-------------------------------
1  | blue  | round | big  | ...
2  | *     | rect  | small| ...
3  | red   | *     | big  | ...

(此表具有与任何选项匹配的通配符)

现在有很多关系,到目前为止没什么特别的 我得到的输入是一组特征(颜色,形状,大小等)的列表,我需要带有那些符合这些特征的相关购物车。

例如 - 用户查询包含2个项目的购物车 -
一个是大而蓝的 秒是小而圆的

我所做的是获取与第一项要求匹配的项目ID列表以及与第二项目匹配的另一个列表。 有了这两个列表,我应该查询一个购物车,其中有2个项目符合这些特征(至少)。 让我们说我从这个查询中收到了两个项目清单 -
对于第一个 - (1,3,5,6,7)
对于第二个 - (3,4,7,9,15)

确保我的购物车有2个项目的最佳查询是什么,一个来自第一个列表,另一个来自第二个列表。我应该说项目数量可以超过2个。

我找到的解决方案是连接' EXISTS'条件,像这样 -

SELECT DISTINCT(cart_id) FROM cart_items ci WHERE 
EXISTS(SELECT 1 FROM cart_items WHERE cart_id = ci.cart_id AND item_id IN <list 1>) 
AND EXISTS(SELECT 1 FROM cart_items WHERE cart_id = ci.ci_cart_id AND item_id IN <list 2>)
AND ...<keep concatenating as long as needed>

很抱歉有长篇描述,有什么建议吗?

1 个答案:

答案 0 :(得分:1)

如果您将查询本身建模为表格,这会有所简化(但是对于您将生成查询的最佳解决方案 - 但使用SQL创建SQL不适合胆小的人,并且您没有标记此用任何其他语言)。因此...

CREATE TABLE queries (
   query_id INTEGER NOT NULL,
   color VARCHAR (20),
   shape VARCHAR (20),
   size VARCHAR (20),
   PRIMARY KEY (query_id, color, shape, size)
);
INSERT INTO queries (query_id, color, shape, size)
VALUES (1, 'blue', '*', 'big');
INSERT INTO queries (query_id, color, shape, size)
VALUES (2, '*', 'round', 'small');

然后您可以通过以下方式识别匹配的项目:

SELECT i.id
FROM items i
INNER JOIN queries q
ON q.color IN (i.color, '*')
AND q.size IN (i.size, '*')
AND q.shape IN (i.shape, '*')
WHERE q.query_id=1;

然后你只需要将它加入cart_items以获得匹配的购物车......

SELECT q.query_id, ci.cart_id
FROM items i
INNER JOIN queries q
ON q.color IN (i.color, '*')
AND q.size IN (i.size, '*')
AND q.shape IN (i.shape, '*')
INNER JOIN cart_items ci
ON i.id=ci.item_id
WHERE q.query_id IN (1,2);

最后,您只需要识别与两个查询匹配的cart_ids:

SELECT COUNT(DISTINCT q.query_id), ci.cart_id
FROM items i
INNER JOIN queries q
ON q.color IN (i.color, '*')
AND q.size IN (i.size, '*')
AND q.shape IN (i.shape, '*')
INNER JOIN cart_items ci
ON i.id=ci.item_id
WHERE q.query_id IN (1,2)
HAVING COUNT(DISTINCT q.query_id)=2;