SQL-запрос к объединенной таблице с несколькими условиями - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть две таблицы sql: таблица wall и таблица tag .Каждый из них связан с отношением has_and_belongs_to_many .Также таблица тегов имеет уникальные имена.

Вот таблицы в sql

mysql> describe tags;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   | UNI | NULL    |                |
| count      | int(11)      | NO   |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

mysql> describe tags_walls;
+---------+------------+------+-----+---------+-------+
| Field   | Type       | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| tag_id  | bigint(20) | NO   | MUL | NULL    |       |
| wall_id | bigint(20) | NO   |     | NULL    |       |
+---------+------------+------+-----+---------+-------+

mysql> describe walls;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

Я нахожусь в рельсах 5, и я хочу запросить стену с несколькими тегами.

Я пытаюсь сделать

result = Wall.all.includes(:tags).where(tags: {name: 'TAG1'})
result = result.where(tags: {name: 'TAG2'})

и запрос, который создается с помощью рельсов:

SELECT  DISTINCT `walls`.`id`
FROM `walls`
LEFT OUTER JOIN `tags_walls` ON `tags_walls`.`wall_id` = `walls`.`id`
LEFT OUTER JOIN `tags` ON `tags`.`id` = `tags_walls`.`tag_id`
WHERE `tags`.`name` = 'TAG1' AND `tags`.`name` = 'TAG2'

В результате я должен получить несколько стен, но результат будет #<ActiveRecord::Relation []>

Я хочу создать собственный SQL-запрос и просто сделать

Wall.includes(:tags).where query

Как я могу выполнить запрос WHERE для объединенной таблицы с несколькими условиями, связанными с помощьюAND?

Ответы [ 3 ]

0 голосов
/ 25 февраля 2019
SELECT w.id
  FROM walls w
  JOIN tags_walls tw
    ON tw.wall_id = w.id
  JOIN tags t
    ON t.id = tw.tag_id
   AND t.name IN('TAG1','TAG2')
 GROUP 
    BY w.id 
HAVING COUNT(DISTINCT t.name) = 2 -- where '2' equals the number of arguments in IN()
0 голосов
/ 25 февраля 2019

Я бы написал так:

SELECT tw.id
FROM tags_walls tw JOIN
     tags t
     ON t.id = tw.tag_id
WHERE t.name IN ('TAG1', 'TAG2')
GROUP BY tw.id
HAVING COUNT(*) = 2;

Это предполагает, что теги не дублируются на стене.Если это возможно, тогда используйте COUNT(DISTINCT t.name) = 2.

Примечания:

  • walls не требуется, так что JOIN удаляется.
  • Youищите совпадения, поэтому INNER JOIN более подходит, чем LEFT JOIN.
  • Псевдонимы таблиц облегчают написание и чтение запроса.
  • Ненужные обратные галочки затрудняют написание запроса ичитать.
0 голосов
/ 25 февраля 2019
WHERE tags.name = 'TAG1' OR tags.name = 'TAG2'

или

WHERE tags.name IN ('TAG1','TAG2')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...