【问题标题】:How do you query the nth value from a list of values by group? MySQL如何按组从值列表中查询第 n 个值? MySQL
【发布时间】:2020-01-15 03:50:33
【问题描述】:

我有一个如下所示的表格:

| thread_id | time       |
| --------- | ---------- |
| 769       | 1566880174 |
| 769       | 1566880415 |
| 769       | 1566884409 |
| 769       | 1566891158 |
| 769       | 1567215554 |
| 769       | 1567227195 |
| 769       | 1567822758 |
| 773       | 1566973984 |
| 773       | 1567216614 |
| 773       | 1567216833 |
| 773       | 1567216913 |
| 773       | 1567216992 |
| 773       | 1567298692 |
| 774       | 1566977378 |
| 774       | 1567218446 |
| 774       | 1567228282 |
| 774       | 1568241410 |
| 784       | 1567300468 |
| 785       | 1567300549 |
| 785       | 1567310667 |
| 785       | 1567310734 |
| 785       | 1567461936 |

我需要获取按 thread_id 分组的第 n 个值。如果我正在寻找每个 thread_id 的第二行,输出应该是这样的

| thread_id | time       |
| --------- | ---------- |
| 769       | 1566880415 |
| 773       | 1567216614 |
| 774       | 1567218446 |
| 784       | null       |
| 785       | 1567310667 |

我怎样才能达到这个结果?

【问题讨论】:

  • 在 (partition by ...) 上放置一个行号作为内部选择,然后使用 where 条件获取第 n 个值...先试一试,如果不成功,粘贴你试过的代码
  • 如果没有 MySQL 8.0,可以使用GROUP_CONCAT() 连接它们,然后使用SUBSTRING_INDEX 选择该字符串的第 N 个元素。见giannistsakiris.com/2015/01/23/…
  • 第n个值按照哪个顺序?

标签: mysql sql mariadb greatest-n-per-group


【解决方案1】:
SELECT NTH_VALUE(thread_id, 2) OVER  (
    PARTITION BY thread_id
    ORDER BY thread_id DESC
) second, time
FROM table_name;

应该是这样的,如果不工作显示输出

【讨论】:

    【解决方案2】:

    如果您不在 MySQL 8.0 上,您可以这样做(如 @Barmar 所建议的那样):

    SELECT thread_id,
           CASE WHEN COUNT(*) >=2 
                THEN SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(TIME ORDER BY TIME) ,',',2),',',-1)
                 ELSE NULL END AS TIME 
      FROM TableA GROUP BY thread_id;
    

    【讨论】:

      【解决方案3】:

      您可以使用行号尝试以下选项-

      SELECT B.thread_id,C.Time 
      FROM (  
          SELECT DISTINCT thread_id FROM your_table A
      )B
      LEFT JOIN (       
          SELECT *,
              @row_num :=IF(@prev_value = concat_ws('',thread_id),@row_num+1,1)AS RowNumber
              , @prev_value := concat_ws('',thread_id) AS Temp
          FROM your_table A,
          (SELECT @row_num := 0) r
          ORDER BY thread_id,`time`
      )C ON B.thread_id = C.thread_id AND C.RowNumber = 2;
      

      【讨论】:

        【解决方案4】:

        一个更简单的解决方案可能如下:

        [假设:time 不是按thread_id 分区排序的]

        select distinct thread_id, lead(2, time) over (partition by thread_id rows between unbounded preceding and unbounded following) as time
        from table_name
        

        这将为每个thread_id 创建一个分区,并将第二个值分配给共享相同thread_id 的所有其他行。您只需要distinct 即可删除所有重复项。

        【讨论】:

          【解决方案5】:

          我有类似的情况,但需要根据数据找到第n个值。 这是我的数据:

          ----------------
          |id |name|score|
          ----------------
          |1  |A   |89   |
          |2  |B   |98   |
          |3  |C   |88   |
          |4  |D   |89   |
          |5  |E   |92   |
          |6  |F   |90   |
          |7  |G   |88   |
          |8  |H   |91   |
          |9  |I   |90   |
          ----------------
          

          要求是找到第 4 高分的学生记录。我使用此查询根据分数获取数据:

          select student.id, student.name, student.score 
          from (select score from student group by score order by score desc limit 3,1) student_temp, student 
          where student_temp.score = student.score
          order by student_temp.score desc ;
          

          基于这个sql我得到了结果:

          ----------------
          |id |name|score|
          ----------------
          |6  |F   |90   |
          |9  |I   |90   |
          ---------------- 
          

          我有编写sql的基本知识。如果他们有任何改进或建议,请发表评论。

          【讨论】:

            猜你喜欢
            • 2021-06-16
            • 2013-07-29
            • 1970-01-01
            • 1970-01-01
            • 2018-10-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多