美文网首页
Leetcode1127. 用户购买平台

Leetcode1127. 用户购买平台

作者: kaka22 | 来源:发表于2020-07-17 10:39 被阅读0次

    题目
    支出表: Spending

    +-------------+---------+
    | Column Name | Type    |
    +-------------+---------+
    | user_id     | int     |
    | spend_date  | date    |
    | platform    | enum    | 
    | amount      | int     |
    +-------------+---------+
    

    这张表记录了用户在一个在线购物网站的支出历史,该在线购物平台同时拥有桌面端('desktop')和手机端('mobile')的应用程序。
    这张表的主键是 (user_id, spend_date, platform)。
    平台列 platform 是一种 ENUM ,类型为('desktop', 'mobile')。

    写一段 SQL 来查找每天 仅 使用手机端用户、仅 使用桌面端用户和 同时 使用桌面端和手机端的用户人数和总支出金额。

    查询结果格式如下例所示:

    Spending table:

    +---------+------------+----------+--------+
    | user_id | spend_date | platform | amount |
    +---------+------------+----------+--------+
    | 1       | 2019-07-01 | mobile   | 100    |
    | 1       | 2019-07-01 | desktop  | 100    |
    | 2       | 2019-07-01 | mobile   | 100    |
    | 2       | 2019-07-02 | mobile   | 100    |
    | 3       | 2019-07-01 | desktop  | 100    |
    | 3       | 2019-07-02 | desktop  | 100    |
    +---------+------------+----------+--------+
    

    Result table:

    +------------+----------+--------------+-------------+
    | spend_date | platform | total_amount | total_users |
    +------------+----------+--------------+-------------+
    | 2019-07-01 | desktop  | 100          | 1           |
    | 2019-07-01 | mobile   | 100          | 1           |
    | 2019-07-01 | both     | 200          | 1           |
    | 2019-07-02 | desktop  | 100          | 1           |
    | 2019-07-02 | mobile   | 100          | 1           |
    | 2019-07-02 | both     | 0            | 0           |
    +------------+----------+--------------+-------------+ 
    

    在 2019-07-01, 用户1 同时 使用桌面端和手机端购买, 用户2 仅 使用了手机端购买,而用户3 仅 使用了桌面端购买。
    在 2019-07-02, 用户2 仅 使用了手机端购买, 用户3 仅 使用了桌面端购买,且没有用户 同时 使用桌面端和手机端购买。

    生成数据

    # 建表语句
    
    CREATE TABLE Spending (
      user_id INT,
      spend_date DATE,
      platform ENUM ('desktop', 'mobile'),
      amount INT
    ) ;
    
    # 插入测试数据
    INSERT INTO Spending ( user_id, spend_date, platform, amount ) VALUES (1, '2019-07-01', 'mobile', 100) ; 
    INSERT INTO Spending ( user_id, spend_date, platform, amount ) VALUES (1, '2019-07-01', 'desktop', 100) ; 
    INSERT INTO Spending ( user_id, spend_date, platform, amount ) VALUES (2, '2019-07-01', 'mobile', 100) ; 
    INSERT INTO Spending ( user_id, spend_date, platform, amount ) VALUES (2, '2019-07-02', 'mobile', 100) ; 
    INSERT INTO Spending ( user_id, spend_date, platform, amount ) VALUES (3, '2019-07-01', 'desktop', 100) ; 
    INSERT INTO Spending ( user_id, spend_date, platform, amount ) VALUES (3, '2019-07-02', 'desktop', 100) ; 
    INSERT INTO Spending ( user_id, spend_date, platform, amount ) VALUES (3, '2019-07-03', 'desktop', 100) ; 
    

    解答
    对user_id、 spend_date进行分组 统计 platform的数量

    SELECT S.`user_id`, S.`spend_date`, COUNT(DISTINCT S.`platform`) AS num
    FROM Spending AS S
    GROUP BY S.`user_id`, S.`spend_date`;
    

    数量超过两个的即为both 计算一下分组的amount和

    SELECT S.`user_id`, S.`spend_date`, 
    IF(COUNT(DISTINCT S.`platform`) = 1, S.`platform`, 'both') AS platform,
    SUM(S.`amount`) AS amount
    FROM Spending AS S
    GROUP BY S.`user_id`, S.`spend_date`;
    

    对于上表 对时间和platform进行分组统计数量 得到 total_users

    SELECT tmp.`spend_date`, tmp.`platform`, SUM(tmp.amount) AS amount, COUNT(tmp.user_id) 
    FROM (SELECT S.`user_id`, S.`spend_date`, 
    IF(COUNT(DISTINCT S.`platform`) = 1, S.`platform`, 'both') AS platform,
    SUM(S.`amount`) AS amount
    FROM Spending AS S
    GROUP BY S.`user_id`, S.`spend_date`) AS tmp
    GROUP BY tmp.`spend_date`, tmp.`platform`
    
    

    但是题目要求不存在也要放在结果里面,只是结果置0而已。

    一个想法就是把所有日期和三个类型的组合先写出来 这里用笛卡尔乘积即可

    SELECT A.`spend_date`, B.`platform`
    FROM (SELECT DISTINCT S.`spend_date`
    FROM Spending AS S) AS A, 
    (SELECT 'desktop' AS platform UNION
     SELECT 'mobile' AS platform UNION
     SELECT 'both' AS platform
    ) AS B;
    

    所有存在的结果和之前的结果进行左连接

    SELECT all_res.spend_date, all_res.platform, res.amount, res.total_users
    FROM (SELECT A.`spend_date`, B.`platform`
    FROM (SELECT DISTINCT S.`spend_date`
    FROM Spending AS S) AS A, 
    (SELECT 'desktop' AS platform UNION
     SELECT 'mobile' AS platform UNION
     SELECT 'both' AS platform
    ) AS B) AS all_res
    LEFT JOIN (SELECT tmp.`spend_date`, tmp.`platform`, SUM(tmp.amount) AS amount, COUNT(tmp.user_id) AS  total_users
    FROM (SELECT S.`user_id`, S.`spend_date`, 
    IF(COUNT(DISTINCT S.`platform`) = 1, S.`platform`, 'both') AS platform,
    SUM(S.`amount`) AS amount
    FROM Spending AS S
    GROUP BY S.`user_id`, S.`spend_date`) AS tmp
    GROUP BY tmp.`spend_date`, tmp.`platform`) AS res
    ON all_res.spend_date = res.spend_date AND all_res.platform = res.platform
    

    将null转为0 即可

    SELECT all_res.spend_date, all_res.platform, IFNULL(res.amount, 0) AS amount, 
    IFNULL(res.total_users,0) AS total_users
    FROM (SELECT A.`spend_date`, B.`platform`
    FROM (SELECT DISTINCT S.`spend_date`
    FROM Spending AS S) AS A, 
    (SELECT 'desktop' AS platform UNION
     SELECT 'mobile' AS platform UNION
     SELECT 'both' AS platform
    ) AS B) AS all_res
    LEFT JOIN (SELECT tmp.`spend_date`, tmp.`platform`, SUM(tmp.amount) AS amount, COUNT(tmp.user_id) AS  total_users
    FROM (SELECT S.`user_id`, S.`spend_date`, 
    IF(COUNT(DISTINCT S.`platform`) = 1, S.`platform`, 'both') AS platform,
    SUM(S.`amount`) AS amount
    FROM Spending AS S
    GROUP BY S.`user_id`, S.`spend_date`) AS tmp
    GROUP BY tmp.`spend_date`, tmp.`platform`) AS res
    ON all_res.spend_date = res.spend_date AND all_res.platform = res.platform
    GROUP BY all_res.spend_date, all_res.platform;
    

    相关文章

      网友评论

          本文标题:Leetcode1127. 用户购买平台

          本文链接:https://www.haomeiwen.com/subject/kmbwhktx.html