如何获取类似项目的列表

时间:2022-11-26 12:15:36

I have 4 tables:

我有4张桌子:

items

+----+------+---------+-----+
| id | name | city_id | ... |
+----+------+---------+-----+

attributes

+----+------+-----+
| id | name | ... |
+----+------+-----+

item_attribute

+----+---------+--------------+
| id | item_id | attribute_id |
+----+---------+--------------+

city

+----+------+-----+
| id | name | ... |
+----+------+-----+

Items and attributes have relations many-to-many.

项目和属性具有多对多的关系。

Item is located only in one city one-to-many

物品仅位于一对多的城市中


Question:

I'm using php (Laravel). How can I get Items list (with LIMIT) for one Item with similar attributes in one city? Attribute list is never equals for 2 items.

我正在使用php(Laravel)。如何在一个城市中为一个具有相似属性的项目获取项目列表(带LIMIT)?属性列表永远不等于2个项目。

Is it possible to do with MySQL query?

是否可以使用MySQL查询?


Example:

| ItemName | Attributes            | City |
+----------+-----------------------+------+
| Alpha    | one, two, three, four | NY   |
| Beta     | five, six, seven      | NY   |
| Gamma    | one, three, seven     | NY   |
| Delta    | one, six, eight       | CA   |
| Epsilon  | two, three, four      | NY   |
| Zeta     | ten, nine             | NY   |

I want to choose similar items for Alpha, they will be: Gamma, Epsilon because they have similar attributes.

我想为Alpha选择类似的项目,它们将是:Gamma,Epsilon,因为它们具有相似的属性。

Delta won't be chosen, because it's located in another city.

Delta将不会被选中,因为它位于另一个城市。

2 个解决方案

#1


1  

If you have both the item_id and the city_id to pass in:

如果您同时传入item_id和city_id:

   SELECT i.name,
          GROUP_CONCAT(a.name) attributes,
          c.name
     FROM items i
     JOIN city c
       ON c.id = i.city_id
     JOIN item_attribute ia
       ON ia.item_id = i.id
      AND EXISTS (
       SELECT 1 
         FROM item_attribute ia1 
         JOIN item_attribute ia2
           ON ia2.attribute_id = ia1.attribute_id
          AND ia2.item_id = ia.item_id
        WHERE ia1.item_id = :item_id /* Pass in item id variable */
              )
     JOIN attributes a
       ON a.id = ia.attribute_id
    WHERE i.city_id = :city_id /* Pass in city id variable */
 GROUP BY i.name, c.name

If you just want to pass the example item id: (A little bit sloppy, but should work)

如果你只是想传递示例项id :(有点草率,但应该工作)

   SELECT i.name,
          GROUP_CONCAT(a.name) attributes,
          c.name
     FROM items base
     JOIN items i
       ON i.city_id = base.city_id
     JOIN city c
       ON c.id = i.city_id
     JOIN item_attribute ia
       ON ia.item_id = i.id
      AND EXISTS (
       SELECT 1 
         FROM item_attribute ia1 
         JOIN item_attribute ia2
           ON ia2.attribute_id = ia1.attribute_id
          AND ia2.item_id = ia.item_id
        WHERE ia1.item_id = base.id
              )
     JOIN attributes a
       ON a.id = ia.attribute_id
    WHERE base.id = :item_id /* Pass in item id variable */
 GROUP BY i.name, c.name

** UPDATE **

**更新**

Ordering:

... 
JOIN (
       SELECT ia2.item_id, COUNT(*) count 
         FROM item_attribute ia1 
         JOIN item_attribute ia2
           ON ia2.attribute_id = ia1.attribute_id
          AND ia2.item_id = ia1.item_id
       /* AND ia2.id != ia1.id /* If you don't want the original item */
        WHERE ia1.item_id = base.id
     GROUP BY ia2.item_id
     ) similar
  ON similar.id = ia.item_id
 ...
ORDER BY similar.count DESC 

#2


0  

You can perform INNER JOINS in all

您可以执行所有INNER JOINS

SELECT I.name,I_A.name,city.name FROM attributes as A
INNER JOIN item_attribute as I_A ON I_A.attribute_id = A.id
INNER JOIN city ON I_A.id = city.id
INNER JOIN items as I ON I.id = I_A.item_id
WHERE <Your condition>

To get comma separated values you can refer here Let me know if I am not getting your point.

要获得逗号分隔值,您可以参考这里。如果我没有明白您的观点,请告诉我。

#1


1  

If you have both the item_id and the city_id to pass in:

如果您同时传入item_id和city_id:

   SELECT i.name,
          GROUP_CONCAT(a.name) attributes,
          c.name
     FROM items i
     JOIN city c
       ON c.id = i.city_id
     JOIN item_attribute ia
       ON ia.item_id = i.id
      AND EXISTS (
       SELECT 1 
         FROM item_attribute ia1 
         JOIN item_attribute ia2
           ON ia2.attribute_id = ia1.attribute_id
          AND ia2.item_id = ia.item_id
        WHERE ia1.item_id = :item_id /* Pass in item id variable */
              )
     JOIN attributes a
       ON a.id = ia.attribute_id
    WHERE i.city_id = :city_id /* Pass in city id variable */
 GROUP BY i.name, c.name

If you just want to pass the example item id: (A little bit sloppy, but should work)

如果你只是想传递示例项id :(有点草率,但应该工作)

   SELECT i.name,
          GROUP_CONCAT(a.name) attributes,
          c.name
     FROM items base
     JOIN items i
       ON i.city_id = base.city_id
     JOIN city c
       ON c.id = i.city_id
     JOIN item_attribute ia
       ON ia.item_id = i.id
      AND EXISTS (
       SELECT 1 
         FROM item_attribute ia1 
         JOIN item_attribute ia2
           ON ia2.attribute_id = ia1.attribute_id
          AND ia2.item_id = ia.item_id
        WHERE ia1.item_id = base.id
              )
     JOIN attributes a
       ON a.id = ia.attribute_id
    WHERE base.id = :item_id /* Pass in item id variable */
 GROUP BY i.name, c.name

** UPDATE **

**更新**

Ordering:

... 
JOIN (
       SELECT ia2.item_id, COUNT(*) count 
         FROM item_attribute ia1 
         JOIN item_attribute ia2
           ON ia2.attribute_id = ia1.attribute_id
          AND ia2.item_id = ia1.item_id
       /* AND ia2.id != ia1.id /* If you don't want the original item */
        WHERE ia1.item_id = base.id
     GROUP BY ia2.item_id
     ) similar
  ON similar.id = ia.item_id
 ...
ORDER BY similar.count DESC 

#2


0  

You can perform INNER JOINS in all

您可以执行所有INNER JOINS

SELECT I.name,I_A.name,city.name FROM attributes as A
INNER JOIN item_attribute as I_A ON I_A.attribute_id = A.id
INNER JOIN city ON I_A.id = city.id
INNER JOIN items as I ON I.id = I_A.item_id
WHERE <Your condition>

To get comma separated values you can refer here Let me know if I am not getting your point.

要获得逗号分隔值,您可以参考这里。如果我没有明白您的观点,请告诉我。