【问题标题】:Get daily count of users by id returning error通过 id 返回错误获取每日用户数
【发布时间】:2021-07-20 11:38:36
【问题描述】:

我正在尝试从 SQL Server 表中获取每日唯一用户数。

表格外观示例:

user_id start_timestamp     activity
111     08/25/2020 13:23    aaaa
111     08/25/2020 14:24    bbbb
222     08/25/2020 14:26    cccc
222     08/25/2020 14:28    dddd
333     08/25/2020 14:31    eeee

我正在寻找的结果表示例:

user_id start_date  count
111     08/25/2020  2
222     08/25/2020  2
333     08/25/2020  1

这是我尝试过的。 '

SELECT 
    [user_id],  
    CONVERT(VARCHAR,[start_timestamp], 23) as [start_date]
    COUNT([user_id]) AS [user_count]
  FROM [dbo].[user_activity]
  GROUP BY [user_id],[start_date]
  ORDER BY [start_date]

我不得不将日期从时间戳转换为分组日期,但我不断收到错误消息:

列名“start_date”无效。

【问题讨论】:

    标签: sql sql-server tsql group-by


    【解决方案1】:

    在单个 select 语句中,您无法使用 group by 子句中的 select 子句设置的别名。

    SELECT 
        [user_id],  
        CONVERT(VARCHAR,[start_timestamp], 23) as [start_date] --<< established here
        COUNT([user_id]) AS [user_count]
    FROM [dbo].[user_activity]
    GROUP BY [user_id],[start_date] --<< illegal reuse of alias here
    ORDER BY [start_date]
    

    您可以通过简单地重复别名之前的信息来避免这种情况,就像这样

    SELECT 
        [user_id],  
        CONVERT(VARCHAR,[start_timestamp], 23) as [start_date] --<< established here
        COUNT([user_id]) AS [user_count]
    FROM [dbo].[user_activity]
    GROUP BY [user_id],CONVERT(VARCHAR,[start_timestamp], 23) --<< no alias here
    ORDER BY [start_date]
    

    我希望看到您将时间戳转换为日期而不是转换为字符串。

    SELECT 
        [user_id],  
        cast([start_timestamp] as date) as [start_date] --<< alias established here
        COUNT([user_id]) AS [user_count]
    FROM [dbo].[user_activity]
    GROUP BY [user_id],cast([start_timestamp] as date)
    ORDER BY [start_date]
    

    【讨论】:

    • 不要在 SQL Server 中使用没有长度的VARCHAR。默认长度因上下文而异,这只是一个非常糟糕的习惯,会导致某些部分的编码错误。
    【解决方案2】:

    您需要将转换后的日期列按部分添加到 grıup。

    SELECT 
        [user_id],  
        CONVERT(VARCHAR,[start_timestamp], 23) as [start_date]
        COUNT([user_id]) AS [user_count]
      FROM [dbo].[user_activity]
      GROUP BY [user_id],CONVERT(VARCHAR,[start_timestamp], 23)
      ORDER BY [start_date]
    

    【讨论】:

      【解决方案3】:

      列别名[start_date] 是在评估GROUP BY 之后创建的

      改为使用派生表(子查询)先获取[start_date],然后再获取GROUP BY

      SELECT 
          [user_id],  
          [start_date]
          COUNT([user_id]) AS [user_count]
      FROM
      (
        SELECT 
            [user_id],
            CONVERT(VARCHAR,[start_timestamp], 23) as [start_date]
        FROM [dbo].[user_activity]
      ) dt
      GROUP BY [user_id], [start_date]
      ORDER BY [start_date]
      

      【讨论】:

        【解决方案4】:

        您不应转换为varchar 来获取没有时间的日期。而是转换为date

        正如其他人所提到的,您不能在 group by 中重复使用 select 别名。您可以再次重复相同的convert,但更好的方法是将其放入cross apply,这样您以后可以重复使用它。

        您还应该使用正确的表别名。

        SELECT 
            u.user_id,  
            v.start_date
            COUNT(user_id) AS user_count
          FROM dbo.user_activity u
          CROSS APPLY (VALUES( CAST(u.start_timestamp AS date) ) v(start_date)
          GROUP BY u.user_id, v.start_date
          ORDER BY v.start_date
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多