我有两个表,一个表是黑客学生的名字,另一个表是他们所面临的挑战。我需要返回ID,黑客的名称和攻击次数,例如:
hacker_id name challenges_created
21283 Angela 6
88255 Patrick 5
5077 Rose 4
62743 Frank 4
96196 Lisa 1
但是,如果一个以上的黑客提出了相同数量的挑战,而这个数量少于提出最多挑战的黑客数量,则必须将这些黑客排除在结果之外。在这种情况下,必须排除4s。我在网上找到了该问题的确切答案,看起来像这样(已编辑为使用我的表名):
SELECT c.hacker_id, h.name, COUNT(c.hacker_id) AS ctn
FROM Sample0.Hackers as h
LEFT JOIN Sample0.Challenges c ON h.hacker_id = c.hacker_id
GROUP BY h.hacker_id, h.name
HAVING ctn = (SELECT TOP 1 COUNT(c1.challenge_id) FROM Sample0.Challenges AS c1 GROUP BY c1.hacker_id ORDER BY COUNT(*)) OR
ctn NOT IN (SELECT COUNT(c2.challenge_id) FROM Sample0.Challenges AS c2 GROUP BY c2.hacker_id HAVING c2.hacker_id <> c.hacker_id);
我在HAVING子句上遇到错误,说“无效的列名'ctn'”。我只使用过一次HAVING,并且只能在其上使用基本功能。我不知道为什么会给我这个错误。
答案 0 :(得分:1)
我将使用解析函数来处理此问题:
WITH cte AS (
SELECT c.hacker_id, h.name, COUNT(*) AS challenges_created,
RANK() OVER (ORDER BY COUNT(*) DESC) rnk,
COUNT(*) OVER (PARTITION BY COUNT(*)) cnt
FROM Sample0.Hackers as h
LEFT JOIN Sample0.Challenges c
ON h.hacker_id = c.hacker_id
GROUP BY h.hacker_id, h.name
)
SELECT
hacker_id,
name,
challenges_created
FROM cte
WHERE rnk = 1 OR cnt = 1;
这里的想法是,如果汇总记录与最高挑战数并列,或者没有其他具有相同挑战数的记录,则应保留该记录。
答案 1 :(得分:0)
您不能使用内联别名尝试如下
SELECT
c.hacker_id,
h.name,
COUNT(c.hacker_id) AS ctn
FROM Sample0.Hackers as h
left JOIN Sample0.Challenges as c
ON h.hacker_id = c.hacker_id
GROUP BY c.hacker_id, h.name
HAVING COUNT(c.hacker_id) = (SELECT TOP 1 COUNT(c1.challenge_id) FROM Sample0.Challenges AS c1 GROUP BY c1.hacker_id ORDER BY COUNT(*)) OR
COUNT(c.hacker_id) NOT IN (SELECT COUNT(c2.challenge_id) FROM Sample0.Challenges AS c2 where c2.hacker_id <> c.hacker_id GROUP BY c2.hacker_id )
您的选择列和分组列不是来自同一表,因此它引发的错误hacker_id'在HAVING子句中无效