MySQL | 复杂的(对我来说)SQL 语句,怎么办?

Kod*_*.Me 5 mysql

我有一个包含帖子的表和另一个包含第一个表中每个帖子的元选项的表。元选项表是一个键值对比表。

假设我有看起来像这样的帖子表

Posts
---------------------------------------------
id | Other columns ....
---------------------------------------------
1  | data ...
2  | data ...
3  | data ...
4  | data ...
5  | data ...
Run Code Online (Sandbox Code Playgroud)

和看起来像这样的元选项表

Meta
---------------------------------------------
id | post_id | meta_key | meta_value
---------------------------------------------
1  | 1       | views    | 5
2  | 1       | maxViews | 100
3  | 2       | views    | 0
4  | 2       | maxViews | 1000
5  | 1       | publisOn | 2013-05-14 10:41
6  | 1       | auhor    | MyUser
7  | 2       | auhor    | Another author
Run Code Online (Sandbox Code Playgroud)

问题是,如何通过比较 meta_key 值视图和 maxViews 来获得 id 等于 1 的帖子。

例如,只有当视图低于 Meta 表中的 masViews 时,我才喜欢检索 ID 为 1 的帖子 ID。

请问有什么帮助吗?

ype*_*eᵀᴹ 7

假设(post_id, meta_key)有一个UNIQUE约束,你可以加入两次Meta表:

SELECT 
    p.*,                                          -- replace * with the columns you need
    CAST(m1.meta_value AS SIGNED) AS views,
    CAST(m2.meta_value AS SIGNED) AS maxViews
FROM
    posts AS p
  JOIN
    meta AS m1
      ON  m1.meta_key = 'views'
      AND m1.post_id = p.id
  JOIN
    meta AS m2
      ON  m2.meta_key = 'maxViews'
      AND m2.post_id = p.id
WHERE
    CAST(m1.meta_value AS SIGNED) < CAST(m2.meta_value AS SIGNED) ;
Run Code Online (Sandbox Code Playgroud)

这是SQL-Fiddle(感谢@bluefeet)


Tar*_*ryn 6

您可以先对数据进行透视,然后再应用过滤器。为了在 MySQL 中进行数据透视,您可以使用带有CASE表达式的聚合函数:

select p.id,
  cast(max(case 
           when m.meta_key ='views' 
           then m.meta_value end) as unsigned) Views,
  cast(max(case 
           when m.meta_key ='maxViews' 
           then m.meta_value end) as unsigned) MaxViews  
from posts p
left join meta m
  on p.id = m.post_id
group by p.id
Run Code Online (Sandbox Code Playgroud)

这会将数据从行转换为列(参见SQL Fiddle with Demo):

| ID |  VIEWS | MAXVIEWS |
--------------------------
|  1 |      5 |      100 |
|  2 |      0 |     1000 |
|  3 | (null) |   (null) |
|  4 | (null) |   (null) |
|  5 | (null) |   (null) |
Run Code Online (Sandbox Code Playgroud)

数据采用列格式后,您可以应用过滤器:

select *
from
(
  select p.id,
    cast(max(case 
               when m.meta_key ='views' 
               then m.meta_value end) as unsigned) Views,
    cast(max(case 
               when m.meta_key ='maxViews' 
               then m.meta_value end) as unsigned) MaxViews  
  from posts p
  left join meta m
    on p.id = m.post_id
  group by p.id
) src
where Views < MaxViews;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo。这给出了最终结果:

| ID | VIEWS | MAXVIEWS |
-------------------------
|  1 |     5 |      100 |
|  2 |     0 |     1000 |
Run Code Online (Sandbox Code Playgroud)