我有一套记录用于检查许多设备。感兴趣的四个列是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。
对于每件设备,我只需要每月/每年一条记录。因此,如果记录不存在,我只想回到过去并抓取该记录的数据。
谢谢!
答案 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”列引用更改为“月份”以匹配您的格式。