SQL 语法问题 - 分组依据 - Oracle
Posted
技术标签:
【中文标题】SQL 语法问题 - 分组依据 - Oracle【英文标题】:SQL Syntax Issue - Group By - Oracle 【发布时间】:2014-12-06 20:03:41 【问题描述】:虽然我知道标题不是很具体并且我很抱歉,但我需要帮助解决我在使用 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 添加到我的 group by 语句中。我在 SQL 方面不是最棒的,所以如果它很明显,请不要犹豫,叫我出来。
【问题讨论】:
【参考方案1】: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,因为此关键字应用于选择列表中的所有表达式,并且在您的情况下使用它没有意义(在您分组时已经没有重复项)
【讨论】:
【参考方案2】:有两种方法:
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;
-
使用
INLINE
视图。
这里有一个类似的问题How do I use Group By based on a Case statement in Oracle?
【讨论】:
【参考方案3】:首先,您不需要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
s 引入了额外的列,而不是行,因此您将拥有“dog”列和“cat”列。这些可以很容易地用于SELECT
中的逻辑。假设给定的宠物要么是狗要么是猫,但绝不是两者兼而有之,查询只使用MAX()
,而不是在group by
中包含其他列。
从join
条件中删除or
应该会提高性能。
如果您正在学习 SQL,请学习正确的 ANSI 样式 join
语法。一个简单的规则:永远不要在from
子句中使用逗号。
【讨论】:
【参考方案4】:只是另一个关于骑行和可读性的答案。从您的宠物开始并通过 LEFT-JOIN 加入 dog 或 cat 表,只能在其中一张表中找到。如果您允许其他宠物(鸟类、爬行动物等)留下来,您也可以在这些表中添加更多“LEFT JOIN”并调整 case/when 子句。
所以,情况/时间。如果找到狗的宠物号码匹配,那么您就完成了“狗”。如果没有,那么尝试“Cat”就失败了……如果没有,你就有了 else(或将来的任何其他宠物类型)。
我添加了 pet_number 以进行澄清,这也是您组的一部分...如果您有不止一只名为“闪电”的宠物(快狗或猫,每只都有不同的宠物编号),没有歧义。
另外,对于分组依据,我是在主要宠物的宠物编号列上进行的。在 dog 或 cat 表中找到它并不重要......无论在哪个表中找到它都是不同的数字。
最后,删除了 distinct。由于您按每个宠物编号/名称进行分组,并进行汇总,因此不会有任何重复基于生成的宠物类型...
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 表示由于您没有按宠物类型分组,因此并非所有列都属于 group by 聚合的一部分...并且宠物类型不会因特定宠物数量而改变,您可以只需将其更改为
MAX( case/when ) as PetType
(最后,我讨厌尝试在列中嵌入空格。可能会导致您意想不到的问题,尤其是如果您忘记“引用”它们。)
【讨论】:
以上是关于SQL 语法问题 - 分组依据 - Oracle的主要内容,如果未能解决你的问题,请参考以下文章