如何将HAVING应用于列而不是函数

时间:2019-04-06 10:11:48

标签: sql tsql

我有两个表,一个表是黑客学生的名字,另一个表是他们所面临的挑战。我需要返回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,并且只能在其上使用基本功能。我不知道为什么会给我这个错误。

2 个答案:

答案 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子句中无效