【问题标题】:Get consolidated results with following tables使用下表获得综合结果
【发布时间】:2010-05-20 06:14:47
【问题描述】:

我有一个场景。这是我的表结构:

ID          LoginDate             RemovalDate
----------------------------------------
1           2009/08/01            NULL
2           2009/09/12            2010/01/02
3           2009/08/31            2009/10/29
4           2010/02/17            NULL
5           2009/10/18            2009/11/22

我想要一个特定月份没有删除多少 ID 的综合结果。所以结果集应该是

Date         NotRemoved_ID
--------------------------
2009/08      2
2009/09      3
2009/10      3 [One ID got removed in 2009/10]
2010/02      2 [Two got removed in 2009/11 and 2010/01]

请帮忙。

【问题讨论】:

  • 您显示的输出是否基于您提供的输入?我不明白为什么 2009/09 年的 NotRemoved_ID 应该是 3。
  • 好的,就像 1。在 2009/08 年,有 2 个 ID 已登录,但没有一个被关闭。 2. 2009/09 1 个 ID 登录,没有一个被关闭。总计:记录了 3 个。 3. 2009/10 1 个 ID 登录,1 个关闭。总共 3+1 登录 - 1 已关闭。所以 3. 希望这能澄清更多。
  • 确实如此。你在使用 SQL Server 吗?甲骨文? MySQL?

标签: sql count


【解决方案1】:
WITH a AS (SELECT CAST('20090801' AS datetime) LoginDate,
                  CAST(NULL AS datetime) RemovalDate
           UNION ALL SELECT '20090912', '20100102'
           UNION ALL SELECT '20090831', '20091029'
           UNION ALL SELECT '20100217', NULL
           UNION ALL SELECT '20091018', '20091122'),
b AS (SELECT LoginDate [Date], 1 [Amount] FROM a
      UNION ALL SELECT RemovalDate, -1 FROM a),
c AS (SELECT DATEADD(month, DATEDIFF(month, 0, [Date]), 0) [Month], [Amount]
      FROM b),
d AS (SELECT [Month], SUM([Amount]) [Amount] FROM c GROUP BY [Month]),
e AS (SELECT d.[Month], SUM(d2.[Amount]) [Amount]
      FROM d JOIN d d2 ON d2.[Month] <= d.[Month] GROUP BY d.[Month])
SELECT [Month], [Amount] FROM e

【讨论】:

    【解决方案2】:

    远非漂亮,可能还有很多需要优化的地方,但它已经过测试并且可以与 SQL Server 一起使用。

    确保将所有对 @Table 的引用替换为您的实际表名。

    DECLARE @Table TABLE (ID INTEGER, LoginDate DATETIME, RemovalDate DATETIME)
    
    INSERT INTO @Table
    SELECT           1, '2009/08/01', NULL 
    UNION ALL SELECT 2, '2009/09/12', '2010/01/02'
    UNION ALL SELECT 3, '2009/08/31', '2009/10/29' 
    UNION ALL SELECT 4, '2010/02/17', NULL 
    UNION ALL SELECT 5, '2009/10/18', '2009/11/22' 
    
    SELECT  CAST(ld.yr AS VARCHAR(4)) + '/' + RIGHT('0' + CAST(ld.mnth AS VARCHAR(2)), 2), ld.RunningTotal - ISNULL(rd.RunningTotal, 0)
    FROM    (
              SELECT    yr, mnth, RunningTotal = MAX(RunningTotal)
              FROM      (
                          SELECT    yr = YEAR(t1.LoginDate), mnth = MONTH(t1.LoginDate), RunningTotal = COUNT(*)
                          FROM      @Table t1
                                    CROSS JOIN @Table t2 
                          WHERE     t1.LoginDate >= t2.LoginDate
                          GROUP BY  t1.LoginDate
                        ) ld
              GROUP BY  ld.yr, ld.mnth
            ) ld
            LEFT OUTER JOIN (
              SELECT    yr, mnth, RunningTotal = MAX(RunningTotal)
              FROM      (
                          SELECT    yr = YEAR(t1.RemovalDate), mnth = MONTH(t1.RemovalDate), RunningTotal = COUNT(*)
                          FROM      @Table t1
                                    CROSS JOIN @Table t2 
                          WHERE     t1.RemovalDate >= t2.RemovalDate
                          GROUP BY  t1.RemovalDate
                        ) ld
              GROUP BY  ld.yr, ld.mnth
            ) rd ON rd.yr <= ld.yr AND rd.mnth <= ld.mnth
    ORDER BY  
            1, 2                      
    

    【讨论】:

      【解决方案3】:

      我认为你可以这样做:

      Select LoginDate , dbo.fn_NotRemoved( LoginDate ) From YourTable
      

      因此您可以根据需要编写 fn_NotRemoved。但是,这种方式的性能缺陷应该考虑在内。

      希望对你有帮助

      【讨论】:

      • 我正在编写一份无法插入任何函数的报告。直接查询对我有很大帮助。无论如何,谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      相关资源
      最近更新 更多