0

我有这些桌子

places(place_id, place_name)
places_criteria(place_id, criterion_id)
criteria(criterion_id, criterion_name)

“places_criteria”有“places”和“criteria”的外键。我可以通过一个标准获得很多地方。

SELECT p.place_id, p.place_name
FROM places p INNER JOIN places_criteria pc ON p.place_id = pc.place_id
WHERE pc.criterion_id = < some_id >

如何通过多个标准获得许多地方?

例如:迪士尼乐园是一个地方(place_id = 1),它是“好”(criterion_id = 1)和“有趣”(criterion_id = 2)。

places_criteria 的数据:

place_id   criterion_id
1            1
1            2

现在我想获得“好”和“有趣”的地方。

4

4 回答 4

3

硬编码版本是为您需要的每个标准加入表格本身......

SELECT
  c1.place_id
FROM
  places_criteria      AS c1
INNER JOIN
  places_criteria      AS c2
    ON c2.place_id = c1.place_id
WHERE
      c1.criterion_id = 1
  AND c2.criterion_id = 2

这很有效,但如果要查询动态数量的criteria_id,则需要动态SQL。

另一种方法是使用IN (1,2) (或连接等,以执行类似的功能)来获得答案Places with criterion 1 <OR> 2,然后使用HAVING子句仅包含具有两个不同标准的地方。

SELECT
  place_id
FROM
  places_criteria
WHERE
  criterion_id IN (1,2)
GROUP BY
  place_id
HAVING
  COUNT(DISTINCT criterion_id) = 2
于 2012-06-12T07:01:01.450 回答
2

你可以这样做 :

SELECT p.place_id, p.place_name
FROM places p, places_criteria pc1, places_criteria pc2, places_criteria pc3
WHERE p.place_id = pc2.place_id and pc1.criterion_id = < some_id >
and  p.place_id = pc2.place_id and pc2.criterion_id = < some_id >
and p.place_id = pc3.place_id and pc3.criterion_id = < some_id >

但我对你的问题的理解有疑问:你为什么要给我们看这张criteria桌子?

于 2012-06-12T06:37:33.617 回答
1

用于in从集合中选择。您可以使用子选择来获取正确的地点 ID,也可以distinct像我一样使用,这在 MySQL 中可能会更快一些。

select distinct
  p.place_id,
  p.place
from
  places p
  inner join places_criteria pc on pc.place_id = p.place_id
  inner join criteria c on c.criterion_id = pc.criterion_id
where
  /* Either by name */
  c.criterion_name in ('crit A', 'crit B', 'crit C')
  /* Or by id */
  OR c.criterion_id in (1, 2, 3, 4, 5)

解决方案 2. 匹配所有标准。通过检查计数来做到这一点。

select
  p.place_id,
  p.place
from
  places p
  inner join places_criteria pc on pc.place_id = p.place_id
  inner join criteria c on c.criterion_id = pc.criterion_id
where
  c.criterion_name in ('crit A', 'crit B', 'crit C')
group by 
  p.place_id,
  p.place
having
  count(*) = 3 /* the number of criteria */
于 2012-06-12T06:40:12.293 回答
1

如果您想要所有满足以下条件之一的地方:

SELECT p.place_id, p.place_name
FROM places p
INNER JOIN places_criteria pc ON p.place_id = pc.place_id
WHERE pc.criterion_id = < some_id >
OR pc.criterion_id = < some_id2 >
OR pc.criterion_id = < some_id3 >
GROUP BY p.place_id, p.place_name

如果您想要满足所有几个条件的所有地方:

SELECT p.place_id, p.place_name
FROM places p
INNER JOIN places_criteria pc1 ON p.place_id = pc1.place_id
INNER JOIN places_criteria pc2 ON p.place_id = pc2.place_id
INNER JOIN places_criteria pc3 ON p.place_id = pc3.place_id
WHERE pc1.criterion_id = < some_id >
AND pc2.criterion_id = < some_id2 >
AND pc3.criterion_id = < some_id3 >
于 2012-06-12T06:41:17.437 回答