【问题标题】:SQL query on a JOINED table with multiple conditions具有多个条件的 JOINED 表的 SQL 查询
【发布时间】:2019-07-18 23:45:28
【问题描述】:

我有两个 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    |                |
+------------+--------------+------+-----+---------+----------------+

我在 rails 5 中,我想查询具有多个标签的墙。

我正在努力

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

并且由rails构造的查询是

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

我如何对一个由 AND 链接的多个条件的联接表进行 WHERE 查询?

【问题讨论】:

  • 那个查询没有多大意义。您想要 LEFT JOIN,但不选择那些表吗?
  • 向我们展示一些示例表数据和预期结果 - 都是格式化文本,而不是图像。
  • 我用表格数据编辑,我希望有 TAG1 和 TAG2 的墙壁的 IDS

标签: mysql sql ruby-on-rails


【解决方案1】:
WHERE tags.name = 'TAG1' OR tags.name = 'TAG2'

WHERE tags.name IN ('TAG1','TAG2')

【讨论】:

  • 它返回有一个或另一个的墙,我想要两个都有的墙
【解决方案2】:
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()

【讨论】:

    【解决方案3】:

    我会这样写:

    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
    • 您正在寻找匹配项,因此INNER JOINLEFT JOIN 更合适。
    • 表别名使查询更易于编写和阅读。
    • 不必要的反引号使查询更难编写和阅读。

    【讨论】:

      猜你喜欢
      • 2017-02-24
      • 2021-07-26
      • 1970-01-01
      • 2013-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多