选择带有JOIN的DISTINCT返回“操纵”数据

时间:2017-03-28 17:52:30

标签: sql oracle join

我有一个像这样的SQL架构

“考试”表

+--------------+----------+-------------+--------+
| EXAM_ID (PK) | PERSONID | DATEOFSTART | SECRET |
+--------------+----------+-------------+--------+
|            1 |      221 | 2016-01-24  |      0 |
|            2 |      221 | 2017-06-03  |      0 |
|            3 |      221 | 2016-09-17  |      1 |
+--------------+----------+-------------+--------+

“Exam_information”表

+---------------+------------------+---------+-------+
| PERSONID (PK) | DATEOFSTART (PK) | SUBJECT | SCORE |
+---------------+------------------+---------+-------+
|           221 | 2016-01-24       | Math    | A     |
|           221 | 2017-06-03       | Biology | B     |
|           221 | 2016-09-17       | Math    | C+    |
+---------------+------------------+---------+-------+

因此,考试可以在Exam_information表格中提供其他信息。我知道这不是正确设计的架构,但我无法修改它。

最终,我想知道考试不是秘密的人的所有分数。我将逐步构建我的DML,但让我们从基本的JOIN操作开始。

SELECT ei.*
FROM exam_information ei
INNER JOIN exam e
ON ei.personid = e.personid
WHERE ei.personid = 221

这将返回9行数据(因为笛卡尔加入/交叉连接),所以让我们在DISTINCT语句中使用SELECT

SELECT DISTINCT ei.*
FROM exam_information ei
INNER JOIN exam e
ON ei.personid = e.personid
WHERE ei.personid = 221

这将返回3行数据,因此我们似乎在正确的轨道上。我们知道返回3行的其中一行是秘密的,并希望将其排除在外。创建了DML的最终版本。

SELECT DISTINCT ei.*
FROM exam_information ei
INNER JOIN exam e
ON ei.personid = e.personid
WHERE ei.personid = 221
AND e.secret = 0

不知何故(我不是任何SQL大师)这会返回与之前的DML相同的行。三。不像我想的那样两个。

如果我将secret字段添加到我之前的SELECT语句SELECT DISTINCT e.secret, ei.* FROM ...中,我会看到所有3个返回的行都有一个零值作为秘密值,这根本不是真的

我尝试了各种各样的东西,但似乎没有任何效果。

3 个答案:

答案 0 :(得分:0)

你的连接部分关系总是返回3行,因为这个返回3行的

  ON ei.personid = e.personid
  WHERE ei.personid = 

如果您只想要具有秘密0的行,则必须使用dateofstart链接单行

  SELECT DISTINCT ei.*
  FROM   exam_information ei
  INNER JOIN exam e
  ON ei.personid = e.personid and ei.DATEOFSTART  = e.DATEOFSTART 
  WHERE ei.personid = 221
  AND e.secret = 0

答案 1 :(得分:0)

你正在考试中将所有3个考试信息中的EACH记录加入考试中,所以即使你排除了那个秘密的ONE,它仍然会检测到其他2条记录,制作了6条记录,这些记录明显地被归为3条。重新缺少JOIN的标准(作为dateofstart),它将exam_information中的每条记录与考试中的SINGLE记录相匹配,从而允许WHERE过滤器正常工作。

SELECT DISTINCT ei.*
FROM exam_information ei
INNER JOIN exam e
ON ei.personid = e.personid AND ei.dateofstart = e.dateofstart 
WHERE ei.personid = 221
AND e.secret = 0

答案 2 :(得分:0)

这个:

SELET DISTINCT ei.* FROM EXAM_INFORMATION ei
INNER JOIN
(SELECT PERSON_ID, DATEOFSTART FROM EXAM WHERE SECRET = 0) a
ON a.PERSON_ID = ei.PERSON_ID and ei.DATEOFSTART = a.DATEOFSTART
WHERE ei.PERSON_ID = 221;

内表将选择所有没有秘密的考试数据。然后在信息表上执行选择,将其加入内部表 - 这将为您提供非秘密考试数据的所有考试信息,然后最后过滤person_id。