【问题标题】:Get all records for each month. Impute if value not present for particular month and user. SQL获取每个月的所有记录。如果特定月份和用户的值不存在,则进行估算。 SQL
【发布时间】:2021-08-08 10:18:05
【问题描述】:

我在 sql 中有一个以下格式的表格

UserId Month Value
user1 4 12
user1 6 2
user1 12 2
user2 1 4
user2 7 5
user2 9 6

我希望它显示所有用户的所有月份记录。如果用户的月份记录不存在,则该月份的值应为 0。

输出应采用以下格式:

UserId Month Value
user1 1 0
user1 2 0
user1 3 0
user1 4 12
user1 5 0
user1 6 2
user1 7 0
user1 8 0
user1 9 0
user1 10 0
user1 11 0
user1 12 2
user2 1 4
user2 2 0
user2 3 0
user2 4 0
user2 5 0
user2 6 0
user2 7 5
user2 8 0
user2 9 6
user2 10 0
user2 11 0
user2 12 0

【问题讨论】:

  • 请用您正在使用的 DBMS 标记您的问题。我建议您首先创建包含 12 个月值和用户列表的临时表,将它们交叉连接,然后将连接留在您的数据表中

标签: sql


【解决方案1】:

在sql server中

CREATE TABLE #Months ([Month] INT)

DECLARE @i INT = 1

WHILE @i < 13
BEGIN
  INSERT INTO #Months ([Month]) VALUES (@i);
  SET @i = @i + 1
END

SELECT DISTINCT
  UserId,
  m.Month as Month,
  CASE 
    WHEN mt.Month = m.Month
      THEN mt.Value
    ELSE 0
    END AS [Value]
FROM #Months m
CROSS JOIN MyTable mt

DROP TABLE #Months

【讨论】:

  • 我认为这个选项会创建重复的行(示例中为 12 * 6),因为没有限制,交叉连接将做一个完整的笛卡尔
【解决方案2】:

您需要一种方法来生成从 1 到 12 的数字。方法有很多种,包括:

  • select/union all
  • values
  • 子查询
  • 递归 CTE
  • 数字/计数表
  • 特定的数据库功能

没有一种方法适用于所有数据库,但最接近的可能是第一个。

然后的想法是为所有 id 生成所有行,然后引入现有数据:

select u.userid, m.month, coalesce(t.value, 0) as value
from (select distinct userid from t) u cross join
     (select 1 as month union all
      select 2 as month union all
      . . .
     ) m left join
     t
     on t.userid = u.userid and t.month = m.month;

我应该指出,还有其他方法,但这些方法通常与特定数据库更紧密地联系在一起。

【讨论】:

    【解决方案3】:

    您还可以通过将缺少的月份与现有月份合并来添加缺失的月份:

    select * from yourtable y
    
    union all
    
    select distinct UserId, x.Months,0 from yourtable y
    cross join 
    (select months from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) T(months)) x
    where not exists
    (select 1 from yourtable y1 where y1.userid=y.userid and y1.month=x.months)
    

    【讨论】:

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