GROUP BY / HAVING有问题吗? SQL查询未按预期执行

时间:2013-10-24 13:02:12

标签: sql oracle

我有两个问题。此查询提供了正确的结果:

SELECT SFRSTCR_PIDM
FROM SATURN.SFRSTCR 
INNER JOIN SATURN.SSBSECT
     ON SFRSTCR_TERM_CODE = SSBSECT_TERM_CODE
    AND SFRSTCR_CRN = SSBSECT_CRN
    AND (SFRSTCR_RSTS_CODE LIKE 'R%'
     OR  SFRSTCR_RSTS_CODE LIKE 'W%') 
    AND SFRSTCR_CREDIT_HR >= 1 
    AND SSBSECT_SUBJ_CODE IN ('ASTR', 'BIOL', 'CHEM', 'ENVS', 'GEOL', 'PHYS')
    AND SSBSECT_CRSE_NUMB NOT LIKE '%L'
    AND SFRSTCR_TERM_CODE BETWEEN '&BeginAY' AND '&EndAY' 
INNER JOIN SATURN.SHRDGMR
     ON SFRSTCR_PIDM = SHRDGMR_PIDM
    AND SHRDGMR_GRST_CODE = 'AW'
    AND SHRDGMR_TERM_CODE_GRAD BETWEEN '&BeginAY' AND '&EndAY' 
    AND SHRDGMR_MAJR_CODE_1 = '&MajorCode'
GROUP BY SFRSTCR_PIDM
HAVING COUNT(SFRSTCR_CRN) = 2
ORDER BY SFRSTCR_PIDM

返回符合条件的8条记录。

此查询提供的结果不正确:

SELECT SFRSTCR_PIDM,
       SSBSECT_SUBJ_CODE,
       SSBSECT_CRSE_NUMB
FROM SATURN.SFRSTCR 
INNER JOIN SATURN.SSBSECT
     ON SFRSTCR_TERM_CODE = SSBSECT_TERM_CODE
    AND SFRSTCR_CRN = SSBSECT_CRN
    AND (SFRSTCR_RSTS_CODE LIKE 'R%'
     OR  SFRSTCR_RSTS_CODE LIKE 'W%') 
    AND SFRSTCR_CREDIT_HR >= 1 
    AND SSBSECT_SUBJ_CODE IN ('ASTR', 'BIOL', 'CHEM', 'ENVS', 'GEOL', 'PHYS')
    AND SSBSECT_CRSE_NUMB NOT LIKE '%L'
    AND SFRSTCR_TERM_CODE BETWEEN '&BeginAY' AND '&EndAY' 
INNER JOIN SATURN.SHRDGMR
     ON SFRSTCR_PIDM = SHRDGMR_PIDM
    AND SHRDGMR_GRST_CODE = 'AW'
    AND SHRDGMR_TERM_CODE_GRAD BETWEEN '&BeginAY' AND '&EndAY' 
    AND SHRDGMR_MAJR_CODE_1 = '&MajorCode'
GROUP BY SFRSTCR_PIDM, 
         SSBSECT_SUBJ_CODE,
         SSBSECT_CRSE_NUMB
HAVING COUNT(SFRSTCR_CRN) = 2
ORDER BY SFRSTCR_PIDM

我想要它做的是返回16条记录:来自第一个查询的8个SFRSTCR_PIDM应该每次重复两次,并且每条记录应该有一个SSBSECT_SUBJ_CODE和一个SSBSECT_CRSE_NUMB。它实际上做的是给我8条完全不同的SFRSTCR_PIDM记录。

我不确定问题是什么,但我认为有一些方法可以操纵GROUP BY子句使其工作。我很感激一些帮助。

编辑:这有效,但必须有一个更简单的解决方案:

SELECT iv1.SFRSTCR_PIDM, 
       sect2.SSBSECT_SUBJ_CODE, 
       sect2.SSBSECT_CRSE_NUMB
FROM SATURN.SFRSTCR stcr2
   INNER JOIN SATURN.SSBSECT sect2
      ON stcr2.SFRSTCR_TERM_CODE = sect2.SSBSECT_TERM_CODE
     AND stcr2.SFRSTCR_CRN = sect2.SSBSECT_CRN
     AND sect2.SSBSECT_SUBJ_CODE IN ('ASTR', 'BIOL', 'CHEM', 'ENVS', 'GEOL', 'PHYS')
     AND sect2.SSBSECT_CRSE_NUMB NOT LIKE '%L'
     AND stcr2.SFRSTCR_TERM_CODE BETWEEN '&BeginAY' AND '&EndAY' 
   INNER JOIN (SELECT stcr1.SFRSTCR_PIDM
               FROM SATURN.SFRSTCR stcr1
                  INNER JOIN SATURN.SSBSECT sect1
                     ON stcr1.SFRSTCR_TERM_CODE = sect1.SSBSECT_TERM_CODE
                    AND stcr1.SFRSTCR_CRN = sect1.SSBSECT_CRN
                    AND (stcr1.SFRSTCR_RSTS_CODE LIKE 'R%'
                     OR  stcr1.SFRSTCR_RSTS_CODE LIKE 'W%') 
                    AND stcr1.SFRSTCR_CREDIT_HR >= 1
                    AND sect1.SSBSECT_SUBJ_CODE IN ('ASTR', 'BIOL', 'CHEM', 'ENVS', 'GEOL', 'PHYS')
                    AND sect1.SSBSECT_CRSE_NUMB NOT LIKE '%L'
                    AND stcr1.SFRSTCR_TERM_CODE BETWEEN '&BeginAY' AND '&EndAY' 
                  INNER JOIN SATURN.SHRDGMR dgmr1
                     ON stcr1.SFRSTCR_PIDM = dgmr1.SHRDGMR_PIDM
                    AND dgmr1.SHRDGMR_GRST_CODE = 'AW'
                    AND dgmr1.SHRDGMR_TERM_CODE_GRAD BETWEEN '&BeginAY' AND '&EndAY' 
                    AND dgmr1.SHRDGMR_MAJR_CODE_1 = '&MajorCode'
               GROUP BY stcr1.SFRSTCR_PIDM
               HAVING COUNT(stcr1.SFRSTCR_CRN) = 2) iv1
      ON stcr2.SFRSTCR_PIDM = iv1.SFRSTCR_PIDM
ORDER BY iv1.SFRSTCR_PIDM,
         sect2.SSBSECT_SUBJ_CODE, 
         sect2.SSBSECT_CRSE_NUMB

1 个答案:

答案 0 :(得分:0)

这里的问题是向GROUP BY添加两列会使HAVING子句过滤另一组行。

在第一个查询中,您会得到SFRSTCR_PIDMs,其中给定的SFRSTCR_PIDM只有两行JOINs

另一方面,第二个查询仅返回每个组中只有两行由三列组成的行:SFRSTCR_PIDMSSBSECT_SUBJ_CODESSBSECT_CRSE_NUMB。这是完全不同的事情,也是你得到不同结果的原因。

您能提供样本数据和预期结果吗?我还建议你分开加入表的条件和过滤记录的条件 - 更容易看出发生了什么。表DDL也有帮助,最重要的是 - 关于SQLFiddle的一个例子: SQLFiddle