【问题标题】:SQL query to select minimum of 10 resultsSQL 查询以选择最少 10 个结果
【发布时间】:2015-05-20 06:15:39
【问题描述】:

我要返回两种类型的结果:

  • 未读通知
  • 阅读通知

如果有超过 10 个未读通知可用,我想选择尽可能多的通知

如果有

如果我只想选择所有未读通知,我的查询将是:

SELECT * FROM notifications WHERE read = 0

如果我只想选择所有已读通知,我的查询将是:

SELECT * FROM notifications WHERE read = 1

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    这应该对你有帮助:http://sqlfiddle.com/#!9/e7e2a/2

    SELECT * FROM 
    (
        SELECT @rownum := @rownum + 1 AS rownum, name, read
        FROM notifications,
        (SELECT @rownum := 0) r  --initialise @rownum to 0
    ) t
    WHERE read = 0 OR (read = 1 AND rownum <= 10)
    ORDER BY rownum
    

    记录用@rownum 编号。 where 子句确保首先选择 read=0。如果它们达到 10 或更多,则全部被选中。但如果不是,则检查第二个条件(read = 1 AND rownum &lt;= 10)

    (SELECT @rownum := 0) r@rownum 初始化为 0,否则将是 NULLNULL+1=NULL

    【讨论】:

    • 你能解释一下这里发生了什么吗?特别是 r
    • 感谢您的解释!很好的答案。
    • 所有行都有编号,从未读到已读。如果未读>= 10,则选择所有未读。如果未读
    • 只是出于好奇,您知道 postgres 相当于 := 吗?那个运算符叫什么?
    • 使用row_number()。在 SQL Server 和 Postgresql 中以不同方式完成 stackoverflow.com/questions/3959692/rownum-in-postgresql
    【解决方案2】:

    你可以做的是将两个结果联合起来,按最重要的顺序排列,然后限制联合:

    SELECT Col1, Col2, ...
    FROM
    (
      SELECT Col1, Col2, `read`, ... FROM notifications WHERE read = 0
      UNION
      SELECT Col1, Col2, `read`, ... FROM notifications WHERE read = 1
    ) x
    ORDER BY x.`read` -- And probably a column like Time?
    LIMIT 10;
    

    SqlFiddle here

    编辑,回复:必须返回 ALL Unread,而不仅仅是前 10 个

    抱歉,我错过了问题的那一部分。我想不出一种优雅的方式来实现这一点,所以 这里有一个~部分解决方案,如果需要,它会使用命令式过程和一个临时表来填充行: 在 MySql 之前使用codingbiz 的解决方案支持窗口函数(例如ROW_NUMBER() OVER (PARTITION BY read ORDER BY Col1 DESC)

    【讨论】:

    • 如果有 15 个未读通知,这不会只返回 10 个结果吗?
    • 是的,这不太对。如果是这样,它可以写得更简单。
    • 是的,两者都很好 - Strawberry 并且仍在解决 ALL 或 Max10 问题。但是,我看不到非必要的解决方案:(
    • @StuartLC 'LIMIT Max(10, Count(unread notifications))' 怎么样?另一种选择是选择所有未读和 10 个已读,而不显示额外的已读,但这样做的效率相当低,因为用户可能需要多下载 50%。
    • 感谢您花时间研究它。 Codebiz 的解决方案对我有用。
    【解决方案3】:

    如果表没有变大,您可以尝试如下加入它们

    SELECT *, 
        ROW_NUMBER() OVER (
            ORDER BY read
        ) AS RowNum 
    FROM (
        SELECT * FROM notifications WHERE read = 0
        UNION 
        SELECT * FROM notifications WHERE read = 1
    
    ) T1
    WHERE T1.read = 0 OR (T1.read = 1 AND T1.RowNum <= 10)
    ORDER BY T1.read DESC
    

    当这些表确实变大时,您可以先尝试对“已读”表进行计数,看看它是否有超过 10 条未读消息,然后根据该结果选择已读或未读消息

    INT @readMessages = SELECT COUNT(*) FROM notifications WHERE read = 0
    
    SELECT CASE 
        WHEN @readMessages > 10 THEN SELECT * FROM notifications WHERE read = 0
        ELSE (
            SELECT * FROM notifications WHERE read = 0
            UNION 
            SELECT * FROM notifications WHERE read = 1 LIMIT 0, 10-@readMessages
        )
    

    不知道这是否都是正确的 MySQL 语法(更像是一个 SQL 人),但也许它可以帮助你。

    【讨论】:

    • 在 MySQL 上没有 ROW_NUMBER()
    • 找到这个:blog.sqlauthority.com/2014/03/08/… SET \@row_number:=0; SELECT *, \@row_number:=\@row_number+1 AS RowNum FROM (SELECT * FROM notifications WHERE read = 0 UNION SELECT * FROM notifications WHERE read = 1) T1 WHERE T1.read = 0 OR (T1.read = 1 AND T1.RowNum
    【解决方案4】:

    请检查此解决方案。

    SELECT * FROM `notifications` WHERE `read`=1 OR `read`=0  ORDER BY `read` LIMIT 10
    

    http://sqlfiddle.com/#!9/c72af/1

    【讨论】:

      猜你喜欢
      • 2013-10-26
      • 2023-04-08
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 2021-11-12
      • 1970-01-01
      • 2020-09-01
      相关资源
      最近更新 更多