SQL语法问题 - 分组依据 - Oracle

时间:2014-12-06 20:03:41

标签: sql oracle

虽然我知道标题不是非常具体而且我道歉,但我需要帮助解决SQL语法问题,因为我不完全确定语法部分是错误的,我不能更具体。

我正在使用Oracle SQL Developer,如果有帮助的话。

    SELECT DISTINCT pet.PET_NAME,
    CASE
      WHEN dog.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Dog'
      WHEN cat.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Cat'
      ELSE  ''
    END AS "Pet Type",
    SUM(res.RESERVATION_START_DATE - res.RESERVATION_END_DATE) AS "Days Stayed"
    FROM HVK_PET pet, HVK_DOG dog, HVK_CAT cat, HVK_RESERVATION res, HVK_PET_RESERVATION petRes
    WHERE (pet.PET_NUMBER = dog.PET_PET_NUMBER
    OR pet.PET_NUMBER = cat.PET_PET_NUMBER)
    AND res.RESERVATION_NUMBER = petRes.RES_RESERVATION_NUMBER  
    AND petRes.PET_PET_NUMBER = pet.PET_NUMBER
    GROUP BY pet.PET_NAME, dog.pet_pet_number, cat.pet_pet_number;

是我的完整代码,前7行是否带有下划线黄色,并建议将CASE添加到我的分组语句中。我不是SQL上最伟大的,所以如果它显而易见,请毫不犹豫地打电话给我。

4 个答案:

答案 0 :(得分:0)

SELECT pet.PET_NAME,
       CASE
          WHEN dog.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Dog'
          WHEN cat.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Cat'
          ELSE  ''
      END AS "Pet Type",
      SUM(res.RESERVATION_START_DATE - res.RESERVATION_END_DATE) AS "Days Stayed"
    FROM HVK_PET pet, HVK_DOG dog, HVK_CAT cat, HVK_RESERVATION res, HVK_PET_RESERVATION petRes
    WHERE (pet.PET_NUMBER = dog.PET_PET_NUMBER OR pet.PET_NUMBER = cat.PET_PET_NUMBER)
      AND res.RESERVATION_NUMBER = petRes.RES_RESERVATION_NUMBER  
      AND petRes.PET_PET_NUMBER = pet.PET_NUMBER
    GROUP BY pet.PET_NAME, 
             CASE
              WHEN dog.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Dog'
              WHEN cat.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Cat'
              ELSE  ''
            END;

dog.pet_pet_number, cat.pet_pet_number分组不起作用,因为您选择的CASE会以不适合GROUP BY的方式转换结果。

我认为您不需要DISTINCT,因为此关键字已应用于选择列表中的所有表达式,并且在您的情况下将其设置为没有意义(因为您已经没有与之相关的&# 39;重新分组)

答案 1 :(得分:0)

有两种方法:

1

 GROUP BY pet.PET_NAME,
          CASE
             WHEN dog.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Dog'
             WHEN cat.PET_PET_NUMBER = pet.PET_NUMBER THEN 'Cat'
             ELSE  ''
          END;
  1. 使用INLINE视图。
  2. 此处有一个类似的问题How do I use Group By based on a Case statement in Oracle?

答案 2 :(得分:0)

首先,您不需要select distinct。使用group by几乎不需要此构造。

您的case语句的问题在于,它提到了三列,但只有两列在group by中。缺少的列是pet.PET_NUMBER。您可以将其添加到group by,但有更简单的方法来编写查询。

关键是修复join语法而不使用隐式连接:

SELECT pet.PET_NAME,
       MAX(CASE WHEN dog.PET_PET_NUMBER IS NOT NULL THEN 'Dog' ELSE 'CAT' END) AS "Pet Type",
       SUM(res.RESERVATION_START_DATE - res.RESERVATION_END_DATE) AS "Days Stayed"
FROM HVK_PET pet JOIN
     HVK_PET_RESERVATION petRes
     ON petRes.PET_PET_NUMBER = pet.PET_NUMBER JOIN
     HVK_RESERVATION res
     ON res.RESERVATION_NUMBER = petRes.RES_RESERVATION_NUMBER LEFT JOIN
     HVK_DOG dog
     ON pet.PET_NUMBER = dog.PET_PET_NUMBER LEFT JOIN
     HVK_CAT cat
     ON pet.PET_NUMBER = cat.PET_PET_NUMBER
GROUP BY pet.PET_PET_NUMBER, pet.PET_NAME;

left join带来了额外的,而非,因此您将拥有“dog”列和“cat”列。这些可以很容易地用在SELECT的逻辑中。假设某个宠物是狗或猫,但从不两者兼而有之,查询只使用MAX()而不是在group by中包含其他列。

or条件中删除join可以提高效果。

如果您正在学习SQL,请学习正确的ANSI样式join语法。一个简单的规则:永远不要在from子句中使用逗号。

答案 3 :(得分:0)

另一个答案是乘坐和可读性。从您的宠物开始,通过LEFT-JOIN加入狗或猫桌,只能在其中一张桌子上找到。如果您允许其他宠物入住(鸟类,爬行动物等),您可以在这些表格中添加更多“LEFT JOIN”并调整case / when子句。

所以,案例/何时。如果发现狗的宠物编号匹配,那么你就像“狗”一样。如果没有,它会通过尝试“猫”...如果没有,你有你的其他(或将来的任何其他宠物类型)。

我已经添加了pet_number以进行澄清,这也是你的小组的一部分...如果你有多个名为“闪电”的宠物(快狗或猫,每个都有不同的宠物编号),没有歧义。< / p>

另外,对于小组来说,我是在主宠物的宠物编号栏上做的。如果它在狗或猫表中找到它并不重要......无论在哪个表中找到它,它都是不同的数字。

最后,删除了明显的。由于您按每个宠物编号/名称进行分组,并进行总和,因此根据生成的宠物类型不会有任何重复...

SELECT 
      pet.PET_NAME,
      pet.PET_NUMBER,
      CASE WHEN dog.PET_PET_NUMBER IS NOT NULL THEN 'Dog'
           WHEN cat.PET_PET_NUMBER IS NOT NULL THEN 'Cat'
           ELSE  '' END AS "Pet Type",
      SUM(res.RESERVATION_START_DATE - res.RESERVATION_END_DATE) AS "Days Stayed"
   FROM 
      HVK_PET pet
         LEFT JOIN HVK_DOG dog
            ON pet.PET_NUMBER = dog.PET_PET_NUMBER
         LEFT JOIN HVK_CAT cat
            ON pet.PET_NUMBER = cat.PET_PET_NUMBER
         JOIN HVK_PET_RESERVATION petRes
            ON pet.PET_NUMBER = petRes.PET_PET_NUMBER 
            JOIN HVK_RESERVATION res
               ON petRes.RES_RESERVATION_NUMBER = res.RESERVATION_NUMBER
   GROUP BY 
      pet.PET_NAME, 
      pet.PET_NUMBER;

但是,如果Oracle扼杀说不是所有列都是该组聚合的一部分,因为您没有按宠物类型进行分组...并且宠物类型不会因特定宠物编号而改变,您可以只需将其更改为

MAX( case/when ) as PetType

(最后,我讨厌尝试使用嵌入空格的列。可能会导致您可能没有预料到的问题,特别是如果您忘记“引用”它们。)