混合HAVING与MySQL中的CASE或分析函数(PartitionQualify(?

时间:2014-11-03 19:05:42

标签: mysql having window-functions

我有一个SELECT查询返回一些这样的字段:

Date | Campaign_Name | Type | Count_People
Oct  | Cats          | 1    | 500
Oct  | Cats          | 2    | 50
Oct  | Dogs          | 1    | 80
Oct  | Dogs          | 2    | 50

查询使用聚合,我只想在Type = 1时包含结果,然后确保相应的Count_People大于99。

使用示例表,我希望返回两行:Cats。如果狗是1型,它被排除在外,因为它低于100,在这种情况下Dogs = 2也应被排除在外。

换句话说,如果type = 1小于100,则删除相应广告系列名称的所有记录。

我开始尝试这个:

HAVING CASE WHEN type = 1 THEN COUNT(DISTINCT Count_People) > 99 END

我今年早些时候使用过Teradata,并记得使用分析函数" Qualify PartitionBy"进行查询。我怀疑我需要的东西是什么?我需要在运行查询之前将排除基于聚合吗?

我如何在MySQL中执行此操作?我有道理吗?

2 个答案:

答案 0 :(得分:1)

现在我理解了这个问题,我认为最好的选择是确定类型= 1的哪个日期/广告系列组合的count_people大于99的子查询。

SELECT
    <table>.date,
    <table>.campaign_name,
    <table>.type,
    count(distinct count_people) as count_people    
FROM
    (
        SELECT
            date,
            campaign_name           
        FROM
            <table>
        WHERE type=1
        HAVING count(distinct count_people) > 99
        GROUP BY 1,2
    ) type1
    LEFT OUTER JOIN <table> ON
        type1.campaign_name = <table>.campaign_name AND
        type1.date = <table>.date
WHERE <table>.type IN (1,2)
GROUP BY 1,2,3

此处的子查询仅在type = 1且大于99 count_people时返回广告系列/日期组合。它使用LEFT JOIN返回,以确保只有那些广告系列/日期组合才能进入结果集。

主查询上的WHERE将结果仅保留为类型1和类型2,您声明它已经是一个过滤器(虽然在问题中未提及,但它在前一个答案的注释中说明)。

答案 1 :(得分:1)

根据@JNevill回答你的评论,我认为除了使用子选择预过滤你正在处理的记录集之外你别无选择,因为使用HAVING只会限制你正在评估的当前记录 - 无法以这种方式与集合中的先前或后续记录进行比较。

所以看看这样的事情:

SELECT
    full_data.date AS date,
    full_data.campaign_name AS campaign_name,
    full_data.type AS type,
    COUNT(full_data.people) AS people_count
FROM
    (
        SELECT
            date,
            campaign_name,
            type,
            COUNT(people) AS people_count
        FROM table
        WHERE type IN (1,2)
        GROUP BY date, campaign_name, type
    ) AS full_data   
LEFT JOIN
    (
        SELECT
            date,
            campaign_name,
            COUNT(people) AS people_count
        FROM table
        WHERE type = 1
        GROUP BY date, campaign_name
        HAVING people_count < 100
    ) AS filter
ON
    full_data.date = filter.date
    AND full_data.campaign_name = filter.campaign_name
WHERE
    filter.date IS NULL
    AND filter.campaign_name IS NULL

第一个子选择基本上是您当前的查询,而没有尝试使用HAVING过滤掉结果。第二个子选择用于查找具有people_count&gt;的所有日期/广告系列名称组合。 100并将其用作针对完整数据集的过滤器。