如何在MySQL中制作动态限制?

Mar*_* AJ 7 mysql sql sql-limit

我有这样一张桌子:

// notifications
+----+--------------+------+---------+------------+
| id |      event   | seen | id_user | time_stamp |
+----+--------------+------+---------+------------+
| 1  | vote         | 1    | 123     | 1464174617 |
| 2  | comment      | 1    | 456     | 1464174664 |
| 3  | vote         | 1    | 123     | 1464174725 |
| 4  | answer       | 1    | 123     | 1464174813 |
| 5  | comment      | NULL | 456     | 1464174928 |
| 6  | comment      | 1    | 123     | 1464175114 |
| 7  | vote         | NULL | 456     | 1464175317 |
| 8  | answer       | NULL | 123     | 1464175279 |
| 9  | vote         | NULL | 123     | 1464176618 |
+----+--------------+------+---------+------------+ 
Run Code Online (Sandbox Code Playgroud)

我正在尝试为特定用户选择至少15行.只有两个条件:

  1. 始终所有未读的行(seen = NULL)都应匹配,即使它们超过15行.

  2. 如果未读行数大于15,则还应选择2个读取行(seen = 1).


示例: read是读取行unread的数量,是notifications表中未读行的数量.

 read | unread |          output should be           
------|--------|-------------------------------------
 3    | 8      | 11 rows                             
 12   | 5      | 15 rows (5 unread, 10 read)         
 20   | 30     | 32 rows (30 unread, 2 read)         
 10   | 0      | 10 rows (0 unread, 10 read)         
 10   | 1      | 11 rows (1 unread, 10 read)         
 10   | 6      | 15 rows (6 unread, 9 read)          
 100  | 3      | 15 rows (3 unread, 12 read)         
 3    | 100    | 102 rows (100 unread, 2 read)       
Run Code Online (Sandbox Code Playgroud)

这是我当前的查询,它不支持第二个条件.

SELECT id, event, seen, time_stamp 
 FROM notifications n
 WHERE id_user = :id AND seen IS NULL
) UNION 
(SELECT id, event, seen, time_stamp 
 FROM notifications n
 WHERE id_user = :id 
 ORDER BY (seen IS NULL) desc, time_stamp desc
 LIMIT 15
)
ORDER BY (seen IS NULL) desc, time_stamp desc;
Run Code Online (Sandbox Code Playgroud)

Mar*_* AJ 1

我找到解决方案。要添加第二个条件(如果未读行超过 15 行,则选择两个已读行),我必须再使用一个UNION。像这样的东西:

(SELECT id, event, seen, time_stamp 
 FROM notifications n
 WHERE id_user = :id AND seen IS NULL
)UNION
(SELECT id, event, seen, time_stamp
 FROM notification n
 WHERE id_user = :id AND seen IS NOT NULL
 LIMIT 2
)UNION 
(SELECT id, event, seen, time_stamp 
 FROM notifications n
 WHERE id_user = :id 
 ORDER BY (seen IS NULL) desc, time_stamp desc
 LIMIT 15
)
ORDER BY (seen IS NULL) desc, time_stamp desc;
Run Code Online (Sandbox Code Playgroud)

第一个子查询获取所有未见的行。第二个得到两行可见的行。第三个有十五行。删除UNION重复项,但不应用其他限制。