查询使用上一期间的值添加缺失的行

时间:2010-05-27 13:01:06

标签: ms-access

我有一套记录用于检查许多设备。感兴趣的四个列是equip_id, month, year, myData

我的要求是每个设备每月只能有一条记录。

我有一个查询,使数据在equip_id, month, year上唯一。因此,每个月/每年只有一个设备的记录不超过一个。但现在我需要模拟缺失月份的数据。我想简单回过头来获取最后一段数据。

所以这可能看起来令人困惑,所以我将以示例的方式展示。

鉴于此样本数据:

equip_id  month  year  myData
-----------------------------
1         1      2010  500
1         2      2010  600
1         5      2010  800
2         2      2010  300
2         4      2010  400
2         6      2010  500

我想要这个输出:

equip_id  month  year  myData
-----------------------------
1         1      2010  500
1         2      2010  600
1         3      2010  600
1         4      2010  600
1         5      2010  800
2         2      2010  300
2         3      2010  300
2         4      2010  400
2         5      2010  400
2         6      2010  500

请注意,我正在用之前一个月(或两个月等)的数据填写缺失的数据。另请注意,如果装备2的第一个记录是在2010年2月,那么我不需要1/2010的记录,即使我有一个装备1。

对于每件设备,我只需要每月/每年一条记录。因此,如果记录不存在,我只想回到过去并抓取该记录的数据。

谢谢!

2 个答案:

答案 0 :(得分:3)

绝不是完美的:

SELECT equip_id, month, mydata
FROM (

   SELECT equip_id, month, mydata FROM equip
   UNION ALL
   SELECT EquipNum.equip_id, EquipNum.Num, 
     (SELECT Top 1 mydata 
      FROM equip 
      WHERE equip.month<n.num And equip.equip_id=equipnum.equip_id 
      ORDER BY equip.month desc) AS Data
   FROM 
     (SELECT e.equip_id, n.Num 
      FROM 
        (SELECT DISTINCT equip_id FROM equip)  AS e, 
     Numbers AS n)  AS EquipNum 
   LEFT JOIN equip 
   ON (EquipNum.Num = equip.month) 
   AND (EquipNum.equip_id = equip.equip_id)
   WHERE EquipNum.Num<DMax("month","equip")
   AND 
     (SELECT top 1 mydata 
      FROM equip 
      WHERE equip.month<n.num And equip.equip_id=equipnum.equip_id 
      ORDER BY equip.month desc) Is Not Null 
    AND equip.equip_id Is Null AND equip.Month Is Null) AS x
ORDER BY equip_id, month

要使这个工作,你需要一个Numbers表,在这种情况下它只需要保存1到12的整数。我使用的数字表叫做Numbers,字段叫做Num。

编辑多年评论

SELECT equip_id, year, month, mydata
FROM (

   SELECT equip_id, year, month, mydata FROM equip
   UNION ALL
   SELECT en.equip_id, en.year, en.Num, (SELECT Top 1 mydata 
      FROM equip e
      WHERE e.month<n.num And e.year=en.year And e.equip_id=en.equip_id 
      ORDER BY e.month desc) AS Data
   FROM (SELECT e.equip_id, n.Num, y.year
      FROM 
    (SELECT DISTINCT equip_id FROM equip)  AS e, 
    Numbers AS n, 
    (SELECT DISTINCT year FROM equip)  AS y)  AS en 
   LEFT JOIN equip AS e ON en.equip_id = e.equip_id
   AND en.year = e.year
   AND en.Num = e.month
   WHERE en.Num<DMax("month","equip") AND 
     (SELECT Top 1 mydata 
      FROM equip e
      WHERE e.month<n.num And e.year=en.year And e.equip_id=en.equip_id 
      ORDER BY e.month desc) Is Not Null
   AND e.equip_id Is Null 
   AND e.Month Is Null) AS x

ORDER BY equip_id, year, month

答案 1 :(得分:0)

我已经调整了帐户的年份和月份...主要原则与原始查询相同,仅在月份。但是,对于申请一个月和一年,您需要测试年份+月份的设置,即:如果在2009年11月,然后跳到2010年2月会发生什么,您不能仅仅依赖于一个月而不是另一个月,但“集”。所以,我已经应用了年份* 12 +月来防止虚假价值,例如11月= 11 +年= 2009 = 2009 + 11 = 2020,然后2月= 2年= 2010 = 2010 + 2 = 2012 ...但是2009 * 12 = 24108 + Nov = 11 = 24119与2010年相比* 12 = 24120 + 2月= 2 = 24122 - 保持每年/每月组合的正确顺序。其余原则适用。但是,另外一个,我创建了一个表来表示要考虑的年限。对于我的测试,我添加了一个带有2009年11月的Equip_ID = 1条样本,以及2011年2月进入的Equip_ID = 2,并且正确的翻转工作也是如此。 (表C_Years,列= 2009年,2010年,2011年的年份和值)

SELECT 
      PYML.Equip_ID,
      PYML.Year,
      PYML.Mth,
      P1.MyData
   FROM 
      ( SELECT 
             PAll.Equip_ID,
             PAll.Year,
             PAll.Mth,
             ( SELECT MAX( P1.Year*12+P1.Mth )
                   FROM C_Preset P1
                   WHERE PAll.Equip_ID = P1.Equip_ID
                     AND P1.Year*12+P1.Mth <= PAll.CurYrMth) as MaxYrMth
           FROM 
              ( SELECT 
                      PYM1.Equip_ID,
                      Y1.Year,
                      M1.Mth,
                      Y1.Year*12+M1.Mth as CurYrMth
                   FROM 
                      ( SELECT p.equip_id,
                               MIN( p.year*12+p.mth ) as MinYrMth,
                               MAX( p.year*12+p.mth ) as MaxYrMth
                            FROM 
                               C_Preset p
                            group by 
                               1
                      ) PYM1,
                      C_Years Y1,
                      C_Months M1
                   WHERE 
                          Y1.Year*12+M1.Mth >= PYM1.MinYrMth
                      AND Y1.Year*12+M1.Mth <= PYM1.MaxYrMth
              ) PAll
      ) PYML,
      C_Preset P1
   WHERE 
          PYML.Equip_ID = P1.Equip_ID
      AND PYML.MaxYrMth = P1.Year*12+P1.Mth

如果这将是一个重复的事情/报告,我只会创建一个12个月的临时表 - 然后将其用作主表,并对其余数据执行左OUTER连接。通过这种方式,您知道每个月都会得到,但只有在确定了与“另一方”的有效联接时,您才能获得该数据。哎呀...错过了关于填补最后一个元素中缺失元素的观点...思考......

以下作品......我将描述正在发生的事情的要素。首先,我创建了一个临时表“C_Months”,列号为Mth(月),编号为1-12。我使用“Mth”作为Month的缩写,以免与可能的保留字MONTH发生冲突。此外,在我的查询中,表引用“C_Preset”是您提到的已经具有不同元素的准备数据集。

SELECT 
      LVM.Equip_ID,
      LVM.Mth,
      P1.Year,
      P1.MyData
   FROM 
      ( SELECT 
              JEM.Equip_ID,
              JEM.Mth,
              ( SELECT MAX( P.Mth ) 
                   FROM C_Preset P
                   WHERE P.Equip_ID = JEM.Equip_ID
                     AND P.Mth <= JEM.Mth ) as MaxMth
           FROM 
              ( SELECT distinct 
                      p.equip_id,
                      c.mth
                   FROM 
                      C_months c,
                      C_Preset p
                   group by 
                      1, 2
                   HAVING 
                          c.mth >= MIN( p.Mth )
                      and c.mth <= MAX( p.Mth )
                   ORDER BY 
                      1, 2 ) JEM
      ) LVM,
      C_Preset P1
   WHERE 
          LVM.Equip_ID = P1.Equip_ID
      AND LVM.MaxMth = P1.Mth
   ORDER BY 
      1, 2

最内部查询是与给定设备ID关联的可用月份(C_Months)的查询。在您的示例中,设备ID 1的值为1,2,5。因此,这将返回1,2,3,4,5。对于装备ID 2,它以2开始,但以6结束,因此它将返回2,3,4,5,6。因此,别名参考JEM(只是装备月)

然后,MaxMth(最大月份)的字段选择......这是TRICKY ONE

      ( SELECT MAX( P.Mth ) 
           FROM C_Preset P
           WHERE P.Equip_ID = JEM.Equip_ID
             AND P.Mth <= JEM.Mth ) as MaxMth

从此开始,声明我希望与给定设备相关联的最大月份(来自JEM)与有效月份相比(在合格列表中检测到最高“有效”设备项目/月份)。这将导致......

Equip_ID Mth    MaxMth
  1      1      1
  1      2      2
  1      3      2
  1      4      2
  1      5      5

  2      2      2
  2      3      2
  2      4      4
  2      5      4
  2      6      6

因此,对于ID = 1的示例,您有1个月,2个月,5个月(3个和4个丢失),因此3和4所指的最后一个有效月份是序列#2的月份。同样地,对于ID = 2,你有2个月,4个月和6个月......这里,3个将返回2,5个将返回4个。

其余部分很容易。现在,我们将您的LVM(上一个有效月)结果加入到原始C_Preset(较少的记录)中,如上所示。但由于我们现在有最后一个有效月份直接关联到C_Preset中的现有记录,我们按设备ID和MaxMth列连接,而不是实际月份。

希望这会有所帮助......再次,您可能需要将我的“第m”列引用更改为“月份”以匹配您的格式。