【问题标题】:SQL Query comparing several tuples (mysql)SQL查询比较几个元组(mysql)
【发布时间】:2015-11-04 15:06:18
【问题描述】:

最近发过这个问题:SQL query comparing an attribute in multiple tuples based on values of another attribute within the relation

下表相同,但略有修改:

                    Test

    +--------+--------+--------+--------+
    |  Name  |  Date  |Location| Score  |
    +--------+--------+--------+--------+
    | Steven |03-05-12| 120000 |   78   |
    +--------+--------+--------+--------+
    | James  |04-09-11| 110000 |   67   |
    +--------+--------+--------+--------+
    | James  |06-22-11| 110000 |   58   |
    +--------+--------+--------+--------+
    |  Ryan  |10-11-13| 250000 |   62   |
    +--------+--------+--------+--------+
    |  Ryan  |12-19-13| 180000 |   55   |
    +--------+--------+--------+--------+
    |  Ryan  |01-20-15| 180000 |   99   |
    +--------+--------+--------+--------+

请注意,Ryan 的分数会降低,但随后会增加。我之前收到的回复在这种情况下仍然选择 Ryan,尽管他的分数并不总是在增加。我知道我在原来的帖子中可能没有说清楚,但是我可以做任何查询来解决这个问题吗?

谢谢

编辑:对不起,我很快就发布了。

基本上我需要一个查询来选择所有在他们尝试的连续测试中得分较低的人的姓名。

即,不接受瑞恩,但接受詹姆斯

【问题讨论】:

  • 你能不能把这两个问题结合起来,回到那个问题。并相应地重新调整您接受的答案。而不是骗子。我们现在有 3 个主题变体。 3 个问题
  • 另外,明确指出它绝对是 mysql 而不是 Sql Server(或任何情况)。一个人用partition 写了一个Sql Server 答案,因为有些人发现sql 表示Sql Server
  • 虽然不幸的是 OP 无法弄清楚如何提出他真正想要回答的问题,但他返回并从根本上改变他的形式将是一种糟糕的形式其他人在接受他们的答案后。
  • 我没有注意到 Ryan 分数下降但后来又增加了!!!还要清楚在哪些情况下 Ryan 必须输入或输出输出
  • 我同意@JohnBollinger

标签: mysql sql


【解决方案1】:

我认为 John 的回答很好,但我想补充一些信息。

使用此基本查询SqlFiddleDemo,您可以在此处将所有条件包含在left join

select t1.Name, t1.Date, t1.Score, t2.Date, t2.Score
from
  student t1
  left join student t2 
         on t1.Name = t2.Name
        and t1.Date < t2.Date
        and t1.Score <= t2.Score

|   Name |                       Date | Score |                      Date |  Score |
|--------|----------------------------|-------|---------------------------|--------|
|   Ryan |  October, 11 2013 00:00:00 |    62 | January, 20 2015 00:00:00 |     99 |
|   Ryan | December, 19 2013 00:00:00 |    55 | January, 20 2015 00:00:00 |     99 |
| Steven |    March, 05 2012 00:00:00 |    78 |                    (null) | (null) |
|  James |    April, 09 2011 00:00:00 |    67 |                    (null) | (null) |
|  James |     June, 22 2011 00:00:00 |    58 |                    (null) | (null) |
|   Ryan |  January, 20 2015 00:00:00 |    99 |                    (null) | (null) |

然后你可以使用条件SUM 来计算每个名字增加了多少次他的分数。在这种情况下,Ryan 将是 2

select t1.Name, SUM(IF(t2.Date IS NULL, 0, 1)) as increase_score
from
  student t1
  left join student t2 
         on t1.Name = t2.Name
        and t1.Date < t2.Date
        and t1.Score <= t2.Score
GROUP BY t1.Name
HAVING 
    increase_score = 0                    -- not increase score in any test
and count(*) > 1                          -- present more than one test

【讨论】:

  • 我所知道的是:你的返回詹姆斯,约翰的答案返回史蒂文。我必须阅读 Op 的两个问题(这个问题和之前的问题)才能得出这个结论:只有成绩不断下降的学生。我会在使用NOT IN 之前移山。我认为答案是詹姆斯。并且 OP 需要知道如何写一个问题,而不像有人说的那样散落 cookie 屑
  • @Drew 感谢必须在再次阅读评论后修复它以删除那些没有提供多个测试的评论。如果想要将其包含在内,好的部分很容易更改。
  • 嗯,你得到的结果是我所期望的。 :)
【解决方案2】:

更新: 这完全替代了我原来的错误答案。

问题很复杂,因为您想同时选择两个非常不同的标准:

  1. 此人在表Test 中有多行,并且
  2. 给定人员和日期的每一行的得分都低于同一个人在每个较早日期的记录

您正在比较同一个表的不同行这一事实表明通过自联接来解决问题:

FROM
  Test t1
  join Test t2
    on t1.Name = t2.Name

如果我们过滤掉将每一行连接到自身所产生的结果,那么只会留下与被多行引用的人相关的行。此外,对于具有相同Name 的行 R1 和 R2,我们只需要考虑 (R1, R2) 和 (R2, R1) 对之一。我们可以用一个过滤器解决这两个问题:

WHERE t1.Date < t2.Date

我们希望在Name-by-Name 的基础上对连接结果进行分析;建议聚合查询(如果有合适的聚合函数可用):

GROUP BY t1.Name

我们只想要那些满足我们条件的聚合,这些条件是通过WHERE 过滤器的每一行,因此有t1.Date &lt; t2.Date,也有t1.Score &gt; t2.Score。我们可以依赖关系运算符计算为数字的事实:1 为真,0 为假。如果我们在每个组中添加这些值,我们可以确定每一行是否满足标准:

HAVING SUM(t1.Score > t2.Score) = COUNT(*)

鉴于我们只想选择名称(由于分组方便,它们已经很容易区分),所有这些都聚集在一起

SELECT t1.Name
FROM
  Test t1
  join Test t2
    on t1.Name = t2.Name
WHERE t1.Date < t2.Date
GROUP BY t1.Name
HAVING SUM(t1.Score > t2.Score) = COUNT(*)

这是一个小提琴,样本数据来自问题:http://sqlfiddle.com/#!9/8dcba/16/0

【讨论】:

  • 更新了一个完全修改的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 2012-02-01
  • 1970-01-01
相关资源
最近更新 更多