【问题标题】:Is there any SQL Syntax that will help me find if things are in descending order?是否有任何 SQL 语法可以帮助我查找事物是否按降序排列?
【发布时间】:2020-03-11 07:31:54
【问题描述】:

举个例子,如果我想在这个表中找到每个司机的 driver_ssn,他们的考试分数随着他们参加更多的考试而连续降低。

下面的示例数据:

Driver_ssn Branch_id Exam_date Exam_type Exam_score
11111111   20       2017-05-25     D         79
11111111   20       2017-12-02     L         67
22222222   30       2016-05-06     L         25
22222222   40       2016-06-10     L         51
22222222   40       2016-08-29     D         81
33333333   10       2017-07-07     L         45
33333333   20       2017-06-27     L         49
33333333   20       2017-07-27     L         61
44444444   10       2017-07-27     L         71
44444444   20       2017-08-30     L         65
44444444   40       2017-09-01     L         62

我没有可发布的查询,因为我对 SQL 很陌生,不知道从哪里开始。

我使用的是 8.0.18 版本

【问题讨论】:

  • 'in this table' - 那是什么表?请添加示例数据(作为文本)
  • 请添加您的查询并详细说明问题
  • 如果您使用的是 mysql 8 或更高版本,请搜索 RANK 和 DENSE_RANK。 (告诉我们你使用的版本)

标签: mysql sql mysql-8.0


【解决方案1】:

使用lag() 查看之前的分数在哪里更大。然后使用聚合来确保这永远不会发生:

select driver_ssn
from (select e.*,
             lag(exam_score) over (partition by driver_ssn order by exam_date) as prev_exam_score
      from exams e
     ) e
group by Driver_ssn
having sum(prev_exam_score >= exam_score) = 0;

也就是说,不存在上一次考试成绩大于或等于下一次考试成绩的情况。

【讨论】:

    【解决方案2】:

    使用LAG 将分数与之前的分数进行比较。使用NOT EXISTSNOT IN 显示所有不存在分数高于前一个考试的ssn。

    select distinct driver_ssn from exams
    where driver_ssn not in
    (
      select driver_ssn
      from
      (
        select
          driver_ssn,
          exam_score,
          lag(exam_score) over (partition by driver_ssn order by exam_date) as prev_exam_score
        from exams
      ) to_compare
      where exam_score >= prev_exam_score
    );
    

    【讨论】:

      【解决方案3】:

      尚未测试,但请尝试一下; returns 1111 and 4444 for the sample data:

      WITH cte AS (
          SELECT driver_ssn
               , ROW_NUMBER() OVER (PARTITION BY driver_ssn ORDER BY exam_date) AS rn1
               , ROW_NUMBER() OVER (PARTITION BY driver_ssn ORDER BY exam_score DESC, exam_date) AS rn2
          FROM t
      )
      SELECT driver_ssn
      FROM cte
      GROUP BY driver_ssn
      HAVING COUNT(CASE WHEN rn1 = rn2 THEN 1 END) = COUNT(*)
      

      基本上,您可以按日期和分数分别为每个驱动程序的行编号。如果存在日期递增和分数递减的模式,那么每一行的行号都是相同的。

      【讨论】:

      • 谢谢!我将不得不更多地研究 ROW_NUMBER() OVER 和 PARTITION BY 以了解它们(不确定是否有办法在没有它们的情况下做到这一点)但这很有帮助!
      • 我喜欢这个解决方案。在 MySQL 中,HAVING 子句也可以写成having sum(rn1 <> rn2) = 0
      • 只是一个观察:ORDER BY exam_score DESC, exam_date 允许以相同分数进行连续考试。如果您想阻止他们,请将此ORDER BY exam_score DESC, exam_date DESC
      【解决方案4】:

      是的,有。您可以在查询中使用 ORDER BY,请参见下面的示例:

      SELECT * FROM your-table ORDER BY column-name DESC
      

      希望这会有所帮助!

      【讨论】:

      • 不幸的是,这不会给我连续降分的 driver_ssn。我理解 ORDER BY 声明,但谢谢。
      猜你喜欢
      • 1970-01-01
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-05
      • 2018-04-25
      相关资源
      最近更新 更多