【问题标题】:combine two sql queries having each a with clause结合两个 sql 查询,每个查询都有一个 with 子句
【发布时间】:2019-02-04 07:57:50
【问题描述】:

我有两个正在为我做这项工作的查询,但我想将它们合并以将结果放在一个表中,而不是将结果复制到 excel 中。

第一个查询给出了 2018 年每月至少有一个订阅到期的用户数量:

    WITH UniqueUsers AS
    (
        SELECT DISTINCT MONTH(ValidTo) ExpireMonth, UserId
        FROM UserInAppPurchase 
        WHERE YEAR(ValidTo) = 2018
    )
    SELECT ExpireMonth, COUNT(UserId) UserCount
    FROM UniqueUsers
    GROUP BY ExpireMonth order by ExpireMonth;

第二个查询给出了 2018 年每月至少购买一次订阅的用户数量:

    WITH UniqueUsers AS
    (
        SELECT DISTINCT MONTH(PurchaseDate) PurchaseMonth, UserId
        FROM UserInAppPurchase 
        WHERE YEAR(PurchaseDate) = 2018
    )

   SELECT PurchaseMonth, COUNT(UserId) UserCount
   FROM UniqueUsers
   GROUP BY PurchaseMonth order by PurchaseMonth;

其实 PurchaseMonth 和 ExpireMonth 是一样的。

我的预期输出是:第 1 列:2018 年的几个月
第二列:第一次查询的结果
第三列:第二个查询的结果

只是复制两个结果并手动组合它们并没有太大的危害,但是我很好奇如何直接在SQL中进行。

感谢您的帮助

【问题讨论】:

  • 你的预期输出是什么
  • 用我的预期输出编辑了我的帖子

标签: sql sql-server


【解决方案1】:

我会取消旋转日期并进行聚合:

SELECT MONTH(dte) as mon,
       COUNT(DISTINCT ExpireUserId) as numExpiredUsers,
       COUNT(DISTINCT PurchaseUserId) as numPurchaseUsers
FROM UserInAppPurchase uiap CROSS APPLY
     (VALUES (ValidTo, UserId, NULL),
             (PurchaseDate, NULL, UserId)
    ) v(dte, ExpireUserId, PurchaseUserId)
WHERE dte >= '2018-01-01' AND dte < '2019-01-01'
GROUP BY MONTH(dte) 
ORDER BY MONTH(dte);

此逻辑确实不需要子查询、显式 JOINs 或 CTE。

【讨论】:

    【解决方案2】:

    你可以这样使用:

    with months as 
    (
    SELECT  MONTH(ValidTo) as month_
    FROM UniqueUsers
    WHERE YEAR(ValidTo) = 2018
    union
    SELECT  MONTH(PurchaseDate)
    FROM UniqueUsers
    WHERE YEAR(PurchaseDate) = 2018
    ),
    
    UniqueUsers AS
    (
        SELECT MONTH(PurchaseDate) as ExpireMonth, 
               COUNT(UserId) UserCount
        FROM UniqueUsers
        WHERE YEAR(ValidTo) = 2018
        GROUP BY MONTH(PurchaseDate)
    ),
    
    
    UniqueUsers1 AS
    (
    
       SELECT MONTH(PurchaseDate) as PurchaseMonth, 
              COUNT(UserId) UserCount1
       FROM UniqueUsers
       WHERE YEAR(PurchaseDate) = 2018
       GROUP BY MONTH(PurchaseDate)
    )
    
    
    select m.month_, 
           u.UserCount,
           u1.UserCount1
    from  months m
          left join UniqueUsers u
             on m.month_ = u.ExpireMonth
          left join UniqueUsers1 u1
             on m.month_ = u1.PurchaseMonth
    order by m.month_;
    

    但我不确定您的 order by 子句是您想要的。您的月份将按 1、11、12 排序。也许您想要另一个顺序,我只是重写了您的查询以便将它们组合起来。

    【讨论】:

      【解决方案3】:

      你来了,你可以加入 CTEs

       ;WITH UniqueUsers1
      AS (
          SELECT DISTINCT MONTH(ValidTo) ExpireMonth
              ,UserId
          FROM UserInAppPurchase
          WHERE YEAR(ValidTo) = 2018
          )
          ,UniqueUsers2
      AS (
          SELECT DISTINCT MONTH(PurchaseDate) PurchaseMonth
              ,UserId
          FROM UserInAppPurchase
          WHERE YEAR(PurchaseDate) = 2018
          )
      SELECT *
      FROM (
          SELECT ExpireMonth
              ,COUNT(UserId) UserCount
          FROM UniqueUsers1 c1
          GROUP BY ExpireMonth
          ) First
      INNER JOIN (
          SELECT PurchaseMonth
              ,COUNT(UserId) UserCount
          FROM UniqueUsers2
          GROUP BY PurchaseMonth
          ) Sec ON First.ExpireMonth = Sec.PurchaseMonth
      

      【讨论】:

      • 所以假设我想在 2019 年这样做。我在 ExpireMonth 中确实有值,但在 PurchaseMonth 中没有值,因为还没有购买。现在,将 2018 替换为 2019 时,结果仅显示 1 月和 2 月,因为 PurchaseMonth 还没有数据。但是我怎样才能强制所有 12 个月呢?那么,当 PurchaseMonth 中什么都不算数时,只显示 0?
      • 此查询使用内连接,这意味着如果 PurchaseMonth 和 ExpireMonth 不同(例如,PurchaseMonth 有 1,ExpireMonth 没有 1),结果查询将不包含 1
      【解决方案4】:

      您可以将每个结果存储在单独的临时表中,例如创建两个临时表,如下所示:

      CREATE Table #ExpiryDates (ExpireMonth int, TotalUsers int)
      CREATE Table #PurchaseDates (PurchaseMonth int, TotalUsers int)
      

      然后将第一个查询结果存入临时表#ExpirayDates

      ;WITH UniqueUsers AS
      (
          SELECT DISTINCT MONTH(ValidTo) ExpireMonth, UserId
          FROM UserInAppPurchase 
          WHERE YEAR(ValidTo) = 2018
      )
      INSERT INTO #ExpiryDates (ExpireMonth, TotalUsers)
      SELECT ExpireMonth, COUNT(UserId) UserCount
      FROM UniqueUsers
      GROUP BY ExpireMonth order by ExpireMonth;
      

      第二次查询是这样的:

      ;WITH UniqueUsers AS
      (
          SELECT DISTINCT MONTH(PurchaseDate) PurchaseMonth, UserId
          FROM UserInAppPurchase 
          WHERE YEAR(PurchaseDate) = 2018
      )
      INSERT INTO #PurchaseDates (PurchaseMonth, TotalUsers)
      SELECT PurchaseMonth, COUNT(UserId) UserCount
      FROM UniqueUsers
      GROUP BY PurchaseMonth order by PurchaseMonth;
      

      最后,将这些合并到一个查询中

      SELECT p.PurchaseMonth MonthNumber, p.TotalUsers As UsersMadePurchases, 
             e.ExpireMonth, e.TotalUsers As UsersExpiredSubs 
      FROM #PurchaseDates p
      LEFT JOIN #ExpiryDates e
          ON e.ExpireMonth = p.PurchaseMonth
      

      结果将是:

      MonthNumber UsersMadePurchases  ExpireMonth  UsersExpiredSubs
      4           1                   NULL         NULL
      5           2                   5            2
      6           2                   6            2
      7           1                   7            1
      8           1                   8            1
      

      如果这能解决您的问题,请告诉我。

      【讨论】:

        猜你喜欢
        • 2011-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-19
        • 1970-01-01
        • 1970-01-01
        • 2014-02-23
        • 1970-01-01
        相关资源
        最近更新 更多