【问题标题】:Condition on multiple values in the same column in SQLSQL中同一列中的多个值的条件
【发布时间】:2016-09-06 16:58:16
【问题描述】:

首先,提前感谢您的帮助。这是我关于 SOF 的第一个问题。

我有以下 SQL 数据库表。

qualificationTable:

QualId  studentNo   CourseName   Percentage

1       1           A            91 
2       1           B            81
3       1           C            71
4       1           D            61
5       2           A            91
6       2           B            81
7       2           C            71
8       2           D            59

testTable:

TestId  studentNo   testNo  Percentage dateTaken

1       1           1       91         2016-05-02
2       1           2       41         2015-05-02
3       1           3       71         2016-04-02
4       1           1       95         2014-05-02
5       1           2       83         2016-01-02
6       1           3       28         2015-05-02
7       2           1       90         2016-05-02
8       2           2       99         2016-05-02
9       2           3       87         2016-05-02

我分别为课程 A、B、C 和 D 指定了最低百分比。我需要搜索符合所有课程最低标准的学生。

第 2 部分: 该学生还应符合 testTable 中的标准(分别为三个测试 1、2 和 3 指定的最小百分比)。

换句话说,如果学生符合为所有课程单独指定的最低标准(百分比),则应该选择他。现在,testTable 也是如此,那个特定的学生(在qualificationTable 中被选中)应该在testNo 列中为三个测试(1,2 和3)分别指定最低标准(百分比)。

编辑:

我已经更新了 testTable,现在有针对特定学生的多个测试。我需要检查学生是否满足所有 3 项测试指定的最低要求百分比,但是,只有最近参加的每项测试(1,2 和 3)才应该计算在内。如果学生不符合为最近一次测试指定的最低标准,则不应包括在内。

测试用例:

要求的最低资格百分比:

课程A:90课程B:80课程C:70课程D:60

所需的最低测试百分比:

测试 1:90 测试 2:80 测试 3:70

预期输出

studentNo

1

干杯

【问题讨论】:

  • count(distinct CourseName)?
  • 你能发布你的预期输出吗?

标签: mysql sql database algorithm conditional-statements


【解决方案1】:

我刚刚为您的示例数据和测试用例找到了答案:

要求的最低资格百分比:

课程A:90课程B:80课程C:70课程D:60

所需的最低测试百分比:

测试 1:90 测试 2:80 测试 3:70

试试这个,可能对你有帮助;)

SQL Fiddle

MySQL 架构

CREATE TABLE qualificationTable
    (`QualId` int, `studentNo` int, `CourseName` varchar(1), `Percentage` int)
;

INSERT INTO qualificationTable
    (`QualId`, `studentNo`, `CourseName`, `Percentage`)
VALUES
    (1, 1, 'A', 91),
    (2, 1, 'B', 81),
    (3, 1, 'C', 71),
    (4, 1, 'D', 61),
    (5, 2, 'A', 91),
    (6, 2, 'B', 81),
    (7, 2, 'C', 71),
    (8, 2, 'D', 50)
;


CREATE TABLE testTable
    (`TestId` int, `studentNo` int, `testNo` int, `Percentage` int)
;

INSERT INTO testTable
    (`TestId`, `studentNo`, `testNo`, `Percentage`)
VALUES
    (1, 1, 1, 91),
    (2, 1, 2, 81),
    (3, 1, 3, 71),
    (4, 2, 1, 80),
    (5, 2, 2, 99),
    (6, 2, 3, 87)
;

查询 1

select t1.studentNo
from 
(
  select studentNo from qualificationTable
  where (CourseName = 'A' and Percentage >= 90)
  or (CourseName = 'B' and Percentage >= 80)
  or (CourseName = 'C' and Percentage >= 70)
  or (CourseName = 'D' and Percentage >= 60)
  group by studentNo
  having count(1) = 4
) t1 join
( select studentNo from testTable
  where (testNo = '1' and Percentage >= 90)
  or (testNo = '2' and Percentage >= 80)
  or (testNo = '3' and Percentage >= 70)
  group by studentNo
  having count(1) = 3
) t2 on t1.studentNo = t2.studentNo

我只是选择t1 这两个子查询之一来解释它是如何工作的:

  • GROUP BY 可以得到这样的结果,
|学生号 | |-----------| | 1 | | 2 |
  • COUNT 将得到每个组的总数,对于您的样本数据,studentNo(1) 是 4,studentNo(2) 也是 4,但是我们这里也有 where 子句,所以通过这些标准,我们可以找到哪个匹配的是以下记录,
(1, 1, 'A', 91), (2, 1, 'B', 81), (3, 1, 'C', 71), (4, 1, 'D', 61), (5, 2, 'A', 91), (6, 2, 'B', 81), (7, 2, 'C', 71)
  • 这意味着COUNT会给我们studentNo(1)到4,studentNo(2)到3,所以当mysql运行having count(1) = 4时,这个子查询只返回我们studentNo(1)

子查询t2就是这样工作的,当通过studentNo加入这两个子查询时,它会返回你期望的结果。

Results

| studentNo |
|-----------|
|         1 |

已编辑:

select t1.studentNo
from 
(
  select studentNo from qualificationTable
  where (CourseName = 'A' and Percentage >= 90)
  or (CourseName = 'B' and Percentage >= 80)
  or (CourseName = 'C' and Percentage >= 70)
  or (CourseName = 'D' and Percentage >= 60)
  group by studentNo
  having count(1) = 4
) t1 join
( select studentNo
  from (
      select *
      from testTable
      where (testNo, dateTaken) in (
          select testNo, Max(dateTaken) from testTable group by testNo
      )
  ) tmp
  where (testNo = '1' and Percentage >= 90)
  or (testNo = '2' and Percentage >= 80)
  or (testNo = '3' and Percentage >= 70)
  group by studentNo
  having count(1) = 3
) t2 on t1.studentNo = t2.studentNo

【讨论】:

  • 像魅力一样工作:D 您能否快速解释一下 GROUP BY 和 HAVING 的工作原理(在这种情况下)?我是 SQL 新手,发现在线解释很复杂。 ://
  • @Singhal2 当然,我已经更新了我的帖子,请再次检查。
  • 太棒了,所以 COUNT 基本上返回特定学生在 WHERE 子句中满足的条件数?如果该数字等于 4,则选择该学生?甜:D
  • 我已经更新了需求,请你看看。非常感谢
  • @Singhal2 现在你刚刚编辑了testTable,如果你的样本数据就是这样,我认为没有任何学生符合最低标准,想想这个7 2 1 80 2016-05-02记录在testTable
【解决方案2】:
First find students who does not qualify the minimum percentage.

select distinct studentNo
from stdqualificationmaster
where case when CourseName='A' and  Percentage<90 then 'F' 
           when CourseName='B' and  Percentage<80 then 'F'
           when CourseName='C' and  Percentage<70 then 'F'
           when CourseName='D' and  Percentage<60 then 'F'
      end='F'

As a second step we can use above unqualified students result set as filter for required result set.

select * from stdqualificationmaster where studentNo not in 
(    select distinct studentNo
from stdqualificationmaster
where case when CourseName='A' and  Percentage<90 then 'F' 
           when CourseName='B' and  Percentage<80 then 'F'
           when CourseName='C' and  Percentage<70 then 'F'
           when CourseName='D' and  Percentage<60 then 'F'
      end='F')

【讨论】:

  • 有趣的是,假设我们有 100,000 名学生中的 1 名符合条件,这将使我们遍历所有 99,999 名不首先的学生,以便找到符合条件的学生。 +1 方法:)
  • 如果你有知识分享它并且你正在分享它......你不必为了你精湛的态度而将你的态度与 +100 混为一谈:))))
  • 如果我觉得我有点自大,我深表歉意。无意冒犯:/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 2011-05-17
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多