【问题标题】:Get column value where boolean is true, otherwise get the column value where boolean false获取布尔值为真的列值,否则获取布尔值为假的列值
【发布时间】:2015-04-01 16:22:27
【问题描述】:

我有一个表格,其中的数据类似于以下内容。

我一直在使用一个大表,其中包含许多行,带有不同的标志和键。我已经设法将它们分组,以便在标志为真的地方最低,在标志为假的地方最低。

╔══════════════════╦══════╦═══════╗
║      Email       ║ Flag ║  Key  ║
╠══════════════════╬══════╬═══════╣
║ email1@one.com   ║    1 ║ 77731 ║
║ email1@one.com   ║    0 ║ 67980 ║
║ email2@two.com   ║    1 ║ 64417 ║
║ email2@two.com   ║    0 ║ 71733 ║
║ email3@three.com ║    1 ║ 95655 ║
║ email4@four.com  ║    0 ║ 91016 ║
╚══════════════════╩══════╩═══════╝

现在,对于每封不同的电子邮件,如果有一个真假标志,我想返回 true 键值。否则,我想返回最小值。

所以理想的输出应该是这样的:

╔══════════════════╦══════╦═══════╗
║      Email       ║ Flag ║  Key  ║
╠══════════════════╬══════╬═══════╣
║ email1@one.com   ║    1 ║ 77731 ║
║ email2@two.com   ║    1 ║ 64417 ║
║ email3@three.com ║    1 ║ 95655 ║
║ email4@four.com  ║    0 ║ 91016 ║
╚══════════════════╩══════╩═══════╝

我一直在尝试各种分组,有子句,使用前两个中的 case 语句,但不知道该怎么做。

如果有帮助,我只需要电子邮件和密钥。

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    有很多方法,这里有两种。

    方法一

    你可以用这样的 CTE 做到这一点:

    WITH data_cte AS (
        SELECT Email, MAX(CAST(Flag AS INT)) AS Flag
        FROM Data
        GROUP BY Email)
    SELECT Data.* 
    FROM data_cte
    JOIN Data 
        ON Data.Email = data_cte.Email
        AND Data.Flag = data_cte.Flag
    

    要解构它,CTE 部分只获取每封电子邮件的标志的MAX 值(需要CASTINT,因为你不能在MAX 列上MAX)和查询的其余部分将 CTE 连接回表以获取相关数据行。

    方法二

    使用UNION

    SELECT *
    FROM Data
    WHERE Flag = 1
    
    UNION 
    
    SELECT *
    FROM Data
    WHERE Flag = 0
    AND NOT EXISTS(SELECT * 
                   FROM Data AS InnerData
                   WHERE InnerData.Flag = 1 
                   AND InnerData.Email = Data.Email)
    

    【讨论】:

    • 非常感谢。 CTE 就像一个魅力。我想我之前做过一些类似的事情,但我认为聚合并没有像这个那样复杂。我已经尝试过类似于联合的东西,但是由于桌子的大小,它开始变得有点多了。非常感谢这两种选择!
    【解决方案2】:
    SELECT
        A.Email
        ,CASE WHEN A.Cf > A.Sf THEN Mk ELSE Key END AS ChosenKey
    FROM
        (
        SELECT
            Email
            ,Key
            ,COUNT(Flag) Cf
            ,MIN(Key) OVER(PARTITION BY Email ORDER BY Key ASC) AS Mk
            ,SUM(Flag) OVER(PARTITION BY Email) Sf
        FROM
            Table
        ) AS A
    

    也许可以通过类似的方式工作?然后删除您的重复项等。

    【讨论】:

    • 这看起来也可以作为一种解决方案。感谢您的建议。
    【解决方案3】:

    您也可以通过窗口函数来完成此操作:

    SELECT email, flag, key FROM (
        SELECT email, flag, key, ROW_NUMBER() OVER ( PARTITION BY email ORDER BY flag DESC ) AS rn
          FROM mytable
    ) x1
     WHERE rn = 1;
    

    【讨论】:

    • 很好地使用了 Row_Number。没有考虑过这一点,也从未见过这种语法。会记住这一点!
    猜你喜欢
    • 2013-06-05
    • 2013-10-13
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多