简体   繁体   English

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

[英]SQL Syntax Issue - Group By - Oracle

While I know the title isn't very specific and I apologise, I need help with a syntax issue I'm having with SQL, and as I'm not entirely sure as to the part of the syntax thats wrong, I can't be much more specific. 虽然我知道标题不是很具体,我深表歉意,但我需要有关SQL的语法问题的帮助,而且由于我不太确定错误的语法部分,因此我无法更具体。

I'm using Oracle SQL Developer, if that helps. 如果有帮助,我正在使用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;

Is my complete code, the top 7 lines are underlined yellow with the suggestion to add CASE, to my group by statement. 是我完整的代码,前7行用黄色下划线标出,建议在我的group by语句中添加CASE。 I'm not the greatest at SQL, so if it's glaring obvious don't hesitate to call me out on it. 我不是SQL方面的佼佼者,因此,如果显而易见,请立即致电给我。

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;

Grouping by dog.pet_pet_number, cat.pet_pet_number doesn't work because your CASE in the select transforms the result in such a way that it doesn't fit GROUP BY. dog.pet_pet_number, cat.pet_pet_number分组, dog.pet_pet_number, cat.pet_pet_number因为您的CASE在select中以不适合GROUP BY的方式转换结果。

I suppose you don't need DISTINCT as this keyword is applied to the all expressions in the select list and it doesn't make sense to have it in your case (there is already no dublicates as you're grouping) 我想您不需要DISTINCT,因为此关键字已应用于选择列表中的所有表达式,因此在您的情况下使用它是没有意义的(分组时已经没有重复符号)

There are two ways : 有两种方法:

1. 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. Use INLINE view. 使用INLINE视图。

A similar question here How do I use Group By based on a Case statement in Oracle? 这里一个类似的问题, 如何基于Oracle中的Case语句使用Group By?

First, you do not need select distinct . 首先,您不需要select distinct This construct is almost never needed with a group by . group by几乎不需要这种构造。

The problem with your case statement, as written, is that it mentions three columns, but only two are in the group by . 如您所写, case语句的问题在于它提到了三列,但是group by只有两列。 This missing column is pet.PET_NUMBER . 该缺少的列是pet.PET_NUMBER You can add this to the group by , but there are simpler ways to write your query. 您可以通过将其添加到group by ,但是可以使用更简单的方法来编写查询。

The key is to fix the join syntax and not use implicit joins: 关键是要解决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;

The left join s bring in additional columns , not rows so you'll have "dog" columns and "cat" columns. left join带入额外的 ,而不是行,因此您将拥有“ dog”列和“ cat”列。 These can readily be used in logic in the SELECT . 这些可以很容易地在SELECT逻辑中使用。 Under the assumption that a given pet is either a dog or cat but never both, the query just uses MAX() instead of including additional columns in the group by . 假设给定的宠物是狗还是猫,但绝不是两者,则查询仅使用MAX()而不在group by中包括其他列。

Removing the or from the join condition should improve performance. join条件中删除or可以提高性能。

If you are learning SQL, learn proper ANSI style join syntax. 如果你正在学习SQL,学习正确的ANSI风格join语法。 A simple rule: never use commas in the from clause. 一个简单的规则:请勿在from子句中使用逗号。

Just another answer along for the ride and readability. 行驶和可读性的另一个答案。 Starting with your pet and joining to the dog or cat table via LEFT-JOIN, should only be found in one of the tables. 从您的宠物开始,然后通过LEFT-JOIN加入狗或猫的桌子,只能在其中一张桌子中找到。 If you had other pets allowed to stay (birds, reptiles, etc) you could just add more "LEFT JOIN"s to those tables too and adjust the case/when clause. 如果您允许其他宠物入住(鸟类,爬行动物等),您也可以在这些表中添加更多“ LEFT JOIN”并调整case / when子句。

So, the case/when. 所以,这种情况/何时。 If if finds a dog's pet number match, great you are done as "Dog". 如果发现狗的宠物编号匹配,那就太好了,就像“狗”一样。 If not, it falls through to try "Cat"... if not, you have your else (or any other pet types in the future). 如果没有,那就尝试“猫”吧……如果没有,那么您就拥有了其他(或将来的任何其他宠物类型)。

I have added the pet_number for clarification which is also part of your group by... What if you have more than one pet named "Lightning" (fast dog or cat, each with distinct pet numbers), no ambiguity. 为了澄清起见,我添加了pet_number,这也是您小组中的一部分...如果您有不止一只名为“ Lightning”的宠物(快狗或猫,每只都有不同的宠物号),没有歧义怎么办。

Also, for the group by, I am doing it on the main pet's pet number column. 另外,对于分组依据,我正在主要宠物的宠物编号列上进行。 It does not matter if it finds it in the dog or cat table... it is the number that is distinct regardless of which table it is found in. 它是否可以在狗或猫表中找到它无关紧要……无论在哪个表中找到它,数字都是唯一的。

Lastly, removed the distinct. 最后,删除了区别。 Since you are grouping by each pet number/name, and doing an aggregate sum, there would not be any duplicates based on the resulting pet-type... 由于您是按每个宠物编号/名称分组并进行汇总,因此不会根据生成的宠物类型重复任何数据...

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;

However, if Oracle chokes saying that not all columns are part of an aggregate for the group by because you are not grouping by the pet type... and the pet type won't change for the specific pet number, you can just change that to a 但是,如果Oracle表示您不是所有列都不是该分组依据的一部分,因为您没有按宠物类型进行分组……并且该宠物类型不会因特定宠物编号而改变,则只需更改到一个

MAX( case/when ) as PetType

(Finally, I HATE trying to have columns with embedded spaces. Can cause issues you may not expect, especially if you forget to "quote" them.) (最后,我讨厌尝试使用带有嵌入式空格的列。这可能会导致您可能不会想到的问题,尤其是如果您忘记“引用”它们的时候。)

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

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