【问题标题】:One-to-many association SELECT records WHERE two or more conditions一对多关联 SELECT 记录 WHERE 两个或多个条件
【发布时间】:2019-02-06 07:35:29
【问题描述】:

我有两张桌子:

person

+-----+------------+---------------+
| id  | name       | address       |
+-----+------------+---------------+
| 1   | John Smith | 123 North St. |
| 2   | Joe Dirt   | 456 South St. |
+-----+------------+---------------+  

person_fields

+-----+------------+-----------+-------+
| id  | type       | person_id | value |
+-----+------------+-----------+-------+
| 1   | isHappy    | 1         | 1     |
| 2   | hasFriends | 1         | 1     |
| 3   | hasFriends | 2         | 1     |

我想从person 中选择所有isHappyhasFriends 为TRUE 的人。这是我尝试过的:

SELECT person.*
    FROM person
      INNER JOIN person_fields
        ON person.id = person_fields.person_id
    WHERE
      (person_fields.type = 'isHappy' AND person_fields.value IS TRUE)
      AND
      (person_fields.type = 'hasFriends' AND person_fields.value IS TRUE)

很遗憾,这不起作用,因为您不能在 person_fields 中拥有一条具有 type = 'isHappy'type = 'hasFriends' 的记录。我不能OR 这两个条件,因为那样会返回 John Smith 和 Joe Dirt,但我只想要 John Smith,因为他是唯一一个快乐同时有朋友的人。

有什么建议吗?提前致谢!

【问题讨论】:

    标签: mysql


    【解决方案1】:

    标准解决方案如下所示:

    SELECT person_id 
      FROM person_fields 
     WHERE type IN ('ishappy','hasfriends') 
     GROUP 
        BY person_id 
    HAVING COUNT(1) = 2;
    

    ...其中 '2' 等于 IN() 中的参数个数

    请注意,这假定 (person_id,type) 是唯一的

    【讨论】:

    • 我想我应该更明确一点,但我需要SELECT * FROM person。这只会给我person_id
    • 幸运的是,我相信你有能力自己解决这个问题!
    • 当然!其他一些答案运行得更快,但这是另一个可行的选择。
    • 嗯,想象一下如果你有五六个标准。所有这些连接都会变得乏味,对吧?但不管你的船是什么。
    • @vogomatix pedantry 将带你到任何地方 ;-)
    【解决方案2】:

    加入两次:

    SELECT person.*
    FROM person
    INNER JOIN person_fields happy
            ON person.id = happy.person_id AND happy.type='isHappy' AND happy.value
    INNER JOIN person_fields friends
            ON person.id = friends.person_id AND friends.type='hasFriends' AND friends.value
    

    【讨论】:

    • 我明白了。这似乎是有道理的。唯一让我有点怀疑的是:如果我想找到所有 person_fields 表中的 12 个字段为真的人,我必须加入 12 次?
    • 是的,我想你是对的!我明天可能会对此进行测试,然后将其标记为答案。从长远来看,我可能需要重新考虑结构。谢谢!
    • person 表的更多列是最简单的方法。如果您半频繁地更改列,则可能是dynamic columns。索引会有所帮助,但您需要知道正在使用哪些查询。
    • 不知道为什么你被否决了,但这完全有效。我想它不像@vogomatix 的答案那么易读。
    • 我投了赞成票 :) 当我发布类似的答案时,我什至没有注意到它在那里。
    【解决方案3】:

    您可以加入两次person_fields,一次加入isHappy,一次加入hasFriends

    SELECT p.*
    FROM person p 
    INNER JOIN person_fields f1 ON p.id = f1.person_id
    INNER JOIN person_fields f2 ON f1.person_id = f2.person_id 
    WHERE f1.type = 'isHappy' AND f2.type = 'hasFriends'
    

    我不确定value 字段的位置,但如果需要,您可以添加一个额外的条件或两个

    AND f1.value = 1 AND f2.value = 1
    

    【讨论】:

    • 这和@danblack 的答案几乎在同一时间执行,并且是所有答案中最快的。这一个更具可读性。
    【解决方案4】:

    如果你总是知道要检查多少个条件,并且总是想只返回满足所有条件的person记录,那么你可以使用子查询并修改HAVING子句来选择最大值来自person_fieldstype的数量:

    SELECT
      p.id,
      p.name,
      (SELECT COUNT(DISTINCT pf.type) FROM person_fields AS pf WHERE pf.person_id = p.id and pf.value = true) AS types
    FROM
      person AS p
    HAVING types = 2
    

    结果:

    id  name       types
    1   John Smith 2
    

    【讨论】:

    • 我错过了什么?
    • 我也不确定你错过了什么...我喜欢这种技术。不幸的是,我使用的是 Sequelize ORM,虽然您可以使用 HAVING 子句,但我的实际查询非常复杂,不允许使用此选项。
    猜你喜欢
    • 2012-09-13
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多