SQL: 在不同 table 中查找符合条件的条目

SQL: Find entries with matching criteria in different table

我有两个 table,EventEventTag

CREATE TABLE event (
  id INT PRIMARY KEY,
  content TEXT
)

CREATE TABLE event_tag (
  event_id INT,
  type VARCHAR(255),
  value VARCHAR(255)
)

每个事件都有零个或多个标签。我想在 SQL 中表达的查询是:

Give me all Event (all columns in the table) that have associated tags with EventTag.type="foo" and EventTag.value="bar".

这对于 one 标记条件来说很容易(例如,使用连接和 where,如回答 here),但我该如何处理这种情况两个或更多标准?所以:给我关联标签 "foo" 等于 "bar" 和(!)事件标签 "qux" 等于 "quux" 的事件?我想加入标签 table 'n' 次,但我不确定这是否是个好主意。

Select id from EVENT ev INNER JOIN EVENT_TAG et ON ev.id = et.event_ID WHERE et.type = 'foo' AND et.value = 'bar'

显然,您可以在括号中添加任何您想要的内容,以查找您想要的任何类型。

对多个 case/criteria 使用 Or 操作数

 SELECT * FROM Event e join Event_tag on e.eventId = et.eventtagid where ((EventTag.type="foo" and EventTag.value="bar") or (EventTag.type="po" and EventTag.value="yo"))

或者如果值是动态的,则根据您的编程语言接口 SQL,您可以编写查询

例如 java 我可以使用

SELECT * FROM Event e join Event_tag et on e.eventid = et.eventtagid where (EventTag.type=? and EventTag.value=?)

我将上面的 SQL 字符串分配给 Query 并为其设置参数。

解决这个问题最好的办法就是不使用EAV数据库模型(Entity-Attribute-Value)。您 运行 只是这个反模式的众多问题中的第一个。如果您选择不重新设计,在 "EAV model" 上快速 Google 搜索应该会发现一些其他的问题。通常你的 Event table 应该有一列 foo 和一列 qux.

如果您坚持(或被迫)走这条路,您可以使用一个可能的解决方案:

SELECT id, content
FROM Event
WHERE id IN
(
    SELECT
        E.id
    FROM
        Event E
    INNER JOIN Event_Tag T ON
        T.event_id = E.id AND
        (
            (T.type = 'foo' AND T.value = 'bar') OR
            (T.type = 'qux' AND T.value = 'quux')
        )
    GROUP BY
        E.id
    HAVING
        COUNT(*) = 2
)

如果您将各种 type/value 对放入临时 table 或作为 CTE,那么您可以 JOIN 到那个,而不是列出您想要的所有对。不过,该语法将取决于您的 RDBMS。