另一个表中的SQL SELECT条件

jos*_*mes 4 mysql sql entity-attribute-value

我有2个相关的表:

messages
--------

mid subject
--- -----------------
1   Hello world
2   Bye world
3   The third message
4   Last one


properties
----------

pid mid name             value
--- --- ---------------- ----------- 
1   1   read             false
2   1   importance       high
3   2   read             false
4   2   importance       low
5   3   read             true
6   3   importance       low
7   4   read             false
8   4   importance       high
Run Code Online (Sandbox Code Playgroud)

我需要从messages使用properties桌面上的标准中获益.例如:如果我有一个像return unread (read=false) high prio (importance=high) messages它应该返回的标准

mid subject
--- -----------------
1   Hello world
4   Last one
Run Code Online (Sandbox Code Playgroud)

我怎么能用SELECT子句(MySQL方言)得到它?

Bil*_*win 6

在SQL中,WHERE子句中的任何表达式一次只能引用一行.因此,您需要某种方法将属性表中的多行添加到一行结果中.你用自联接做到这一点:

SELECT ...
FROM messages AS m
JOIN properties AS pRead 
    ON m.mid = pRead.mid AND pRead.name = 'read'
JOIN properties AS pImportance 
    ON m.mid = pImportance.mid AND pImportance.name = 'importance'
WHERE pRead.value = 'false' AND pImportance.value = 'high';
Run Code Online (Sandbox Code Playgroud)

这表明使用EAV 反模式有多么尴尬.与使用常规属性进行比较,其中一个属性属于一列:

SELECT ...
FROM messages AS m
WHERE m.read = 'false' AND m.importance = 'high';
Run Code Online (Sandbox Code Playgroud)

顺便说一句,@ Abe Miessler和@Thomas的答案比你想要的更多.它们匹配所有中间值,其中read = false或者important = high.您需要将这些属性与AND的等效项组合在一起.


Abe*_*ler 5

我相信下面的查询将有效.
更新: @Gratzy是对的,这个查询不起作用,看看我建议的结构变化.

SELECT DISTINCT m.id as mid, m.subject
FROM message as m
INNER JOIN properties as p
ON m.mid = p.mid
where (p.name = 'read' and p.value = 'false') or (p.name = 'importance' AND p.value = 'high')
Run Code Online (Sandbox Code Playgroud)

你的属性表的结构似乎有点偏离我...

是否可以像这样构造表:

messages
--------

mid subject           Read      Importance
--- ----------------- --------- ------------
1   Hello world       false     3
2   Bye world         false     1
3   The third message true      1
4   Last one          false     3

importance
----------

iid importanceName
--- --------------
1   low
2   medium
3   high
Run Code Online (Sandbox Code Playgroud)

并使用此查询:

SELECT m.id as mid, m.subject
FROM message as m
where m.read = false AND m.importance = 3
Run Code Online (Sandbox Code Playgroud)

  • 这也可以让你获得MID 2(读错误但是低估),这是我认为他不想要的 (2认同)