繁体   English   中英

带分组依据的Oracle SQL max()-重复值

[英]Oracle SQL max() with group by - duplicated values

这是我创建的查询的简化版本,它提供了我想要的信息(具有选定cpnt_id的所有stud_id的列表,compl_dte中是否有值,但仅当Item的UserInput仅限于1条记录时。

select stud.*, lrnhist.* from
(select s.stud_id,
        i.cpnt_id
from student s, item i
where s.stud_id in [UserInput]
      c.cpnt_id in [UserInput]
) stud
left outer join
(select lh.stud_id,
        lh.cpnt_id,
        max(lh.compl_dte) compl_dte
from learnhist lh
where lh.cpnt_id in [UserInput]
group by lh.stud_id, lh.cpnt_id
) 
on stud.stud_id = lrnhist.stud_id

在UserInput指定2个或更多项目的情况下运行该命令时,它将返回正确的行,但对于stud_id的每个值,compl_dte的返回值始终是相同的(因为我确定使用max(compl_dte))。 我只是不确定我需要做什么以确保返回的compl_dte是stud_id / cpnt_id对的最大值,而不是stud_id的最大值,与cpnt_id无关。

表值:

student
stud_id
1
2
3
4
item
cpnt_id
a
b
c
d
learnhist
stud_id cpnt_id compl_dte
1    a    5/5/2017
1    a    3/3/2016
1    b    10/10/2016
2    c    8/8/2016
3    b    2/2/2017

UserInput为stud_id = *和cpnt_id = a的结果:

stud_id cpnt_id compl_dte
1    a    5/5/2017
2    a
3    a
4    a

哪个是对的。 UserInput为stud_id = *和cpnt_id = a和b的结果:

stud_id cpnt_id compl_dte
1    a    5/5/2017
1    b    5/5/2017
2    a
2    b
3    a    2/2/2017
3    b    2/2/2017
4    a
4    b

这不是我想要的。 在这种情况下,我正在寻找结果:

stud_id cpnt_id compl_dte
1    a    5/5/2017
1    b    10/10/2016
2    a
2    b
3    a
3    b    2/2/2017
4    a
4    b

希望在这里第一篇文章都有意义,我已经在正确的位置提出要求!

我认为问题可能是STUDLRNHIST内联视图之间缺少LRNHIST谓词。
在您提供的查询中, STUD内联视图是STUDENTITEM之间的笛卡尔乘积,然后将其外部连接到LRNHIST视图,该视图确实每个STUD_ID / CPNT_ID对具有一个CMPL_DTE 但是由于OUTER JOIN仅基于STUD_ID谓词, STUD_ID您还将在STUD.CPNT_ID <> LRNHST.CPNT_ID获得匹配STUD.CPNT_ID <> LRNHST.CPNT_ID ,从而提供额外的行。

您将其分解并分别查看内联视图:

对于STUD查询:

SELECT STUDENT.STUD_ID, ITEM.CPNT_ID FROM STUDENT 
CROSS JOIN ITEM
WHERE STUDENT.STUD_ID IN (1,2,3,4)
AND ITEM.CPNT_ID IN ('a','b','c','d');

结果:

stud_id     cpnt_id
1   a
1   b
1   c
1   d
2   a
2   b
2   c
2   d
... etc

因此,我们可以在最终查询中期待所有这些行。

如果您单独查看LRNHST

SELECT LEARNHIST.STUD_ID,
                LEARNHIST.CPNT_ID,
                 MAX(LEARNHIST.COMPL_DTE) COMPL_DTE
                 FROM LEARNHIST
                 GROUP BY LEARNHIST.STUD_ID, LEARNHIST.CPNT_ID;

实际上,每个stud_id-cpnt_id对仅存在一行(在learnhist中存在):

stud_id     cpnt_id     compl_dte
1   b   October, 10 2016 00:00:00
1   a   May, 05 2017 00:00:00
3   b   February, 02 2017 00:00:00
2   c   August, 08 2016 00:00:00

现在,如果仅使用STUD_ID加入, STUD_ID获得May 5th一行,其中STUD具有1 - aLRNHST具有1 - a ,但是您还将获得其中LRNHST具有1 -b的行,因为没有连接基于CPNT_ID谓词。 如果选择全部五列,则可以看到重复项的位置:

SELECT STUD.*, LRNHIST.* FROM (
SELECT STUDENT.STUD_ID, ITEM.CPNT_ID FROM STUDENT 
CROSS JOIN ITEM
WHERE STUDENT.STUD_ID IN (1,2,3,4)
AND ITEM.CPNT_ID IN ('a','b','c','d')) STUD
LEFT OUTER JOIN (SELECT LEARNHIST.STUD_ID,
                LEARNHIST.CPNT_ID,
                 MAX(LEARNHIST.COMPL_DTE) COMPL_DTE
                 FROM LEARNHIST
                 GROUP BY LEARNHIST.STUD_ID, LEARNHIST.CPNT_ID
                ) LRNHIST
ON STUD.STUD_ID = LRNHIST.STUD_ID
ORDER BY 1 ASC, 2 ASC, 3 ASC, 4 ASC, 5 ASC;

结果:

s_stud  s_cpnt  l_stud  l_cpnt  l_compl

1   a   1   a   May, 05 2017 00:00:00
1   a   1   b   October, 10 2016 00:00:00
1   b   1   a   May, 05 2017 00:00:00
1   b   1   b   October, 10 2016 00:00:00
1   c   1   a   May, 05 2017 00:00:00
1   c   1   b   October, 10 2016 00:00:00
1   d   1   a   May, 05 2017 00:00:00
1   d   1   b   October, 10 2016 00:00:00
2   a   2   c   August, 08 2016 00:00:00
... etc

因为这只是在加入stud_id ,无论是OctMay的记录可以随意搭配STUD1-a匹配LRNHST1在它的两个1-a对地表和1-b组。

现在,如果你加入CPNT_ID为好,只有LRNHST符合两者的记录CPNT_IDSTUD_ID将被退回。 (对于1-a May Oct对于1-b 1-a Oct

SELECT STUD.STUD_ID, STUD.CPNT_ID, LRNHIST.COMPL_DTE FROM (
SELECT STUDENT.STUD_ID, ITEM.CPNT_ID FROM STUDENT 
CROSS JOIN ITEM
WHERE STUDENT.STUD_ID IN (1,2,3,4)
AND ITEM.CPNT_ID IN ('a','b','c','d')) STUD
LEFT OUTER JOIN (SELECT LEARNHIST.STUD_ID,
                LEARNHIST.CPNT_ID,
                 MAX(LEARNHIST.COMPL_DTE) COMPL_DTE
                 FROM LEARNHIST
                 GROUP BY LEARNHIST.STUD_ID, LEARNHIST.CPNT_ID
                ) LRNHIST
ON STUD.STUD_ID = LRNHIST.STUD_ID
AND STUD.CPNT_ID = LRNHIST.CPNT_ID
ORDER BY 1 ASC, 2 ASC;

结果:

stud_id     cpnt_id     compl_dte
1   a   May, 05 2017 00:00:00
1   b   October, 10 2016 00:00:00
1   c   (null)
1   d   (null)
2   a   (null)
2   b   (null)
2   c   August, 08 2016 00:00:00
2   d   (null)
... etc

现在你应该有每次只有一排STUD_ID CPNT_ID对,用空的compl_dte没有地方LRNHST记录匹配。

使用分解的子查询。

WITH all_ids AS (
SELECT s.stud_id as stud_id,
       i.cpnt_id as cpnt_id
  FROM student s
CROSS JOIN item i )
SELECT stud_id, cpnt_id, max(lh.compl_dte) as compl_dte
  FROM all_ids
LEFT JOIN learnhist lh USING (stud_id, cpnt_id)
 WHERE cpnt_id IN ('a', 'b')
GROUP BY stud_id, cpnt_id
ORDER BY stud_id;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM