SQL - 从多个表中提取集合,分组,然后求和

时间:2012-05-19 13:00:27

标签: sql sql-server sql-server-2008 sql-server-2005

我需要从表RawData和RawDataMeter中提取数据,并将最后10分钟(相对于TimeStamp)的每个唯一MeterId的'Value'字段求和。使用INNER JOIN通过RawDataId字段连接的RawData和RawDataMeter表仅在BuildingMeter表中存在RawData.BuildingId和RawDataMeter.MeterId时选择记录。即查询需要选择RawData和RawDataMeter表中的字段,只要它们存在于BuildingMeter表中,然后需要获取每个仪表的最新记录(基于TimeStamp),然后检索该仪表的最后10分钟值。一旦它具有这些值,它需要每米计算10分钟的值并输出结果。

我到目前为止的查询是:

SELECT TOP (SELECT COUNT(DISTINCT BuildingMeterId) FROM BuildingMeter)
    MeterId, BuildingId, TimeStamp, Value
FROM
    RawData
    INNER JOIN 
        RawDataMeter 
    ON RawData.RawDataId = RawDataMeter.RawDataId
WHERE
    EXISTS
        (SELECT 
            BuildingId,
            BuildingMeterId
        FROM
            BuildingMeter)
ORDER BY
    TimeStamp DESC

产生以下结果:

1   1   2012-05-16 12:51:00.000 216
2   1   2012-05-16 12:51:00.000 876989
3   1   2012-05-16 12:51:00.000 389164
4   1   2012-05-16 12:51:00.000 1.298896E+07
5   1   2012-05-16 12:51:00.000 283378
6   1   2012-05-16 12:51:00.000 1541438
7   1   2012-05-16 12:51:00.000 4241823
8   1   2012-05-16 12:51:00.000 5761659
9   1   2012-05-16 12:51:00.000 3
10  1   2012-05-16 12:51:00.000 0
11  1   2012-05-16 12:51:00.000 23
12  1   2012-05-16 12:51:00.000 3822836
13  1   2012-05-16 12:51:00.000 4983960
14  1   2012-05-16 12:51:00.000 909497
15  1   2012-05-16 12:51:00.000 7724438

BuildingMeter表样本(我只包括1栋15米的建筑物(这是可变的)):

BuildingId  BuildingMeterId
1   1
1   2
1   3
1   4
1   5
1   6
1   7
1   8
1   9
1   10
1   11
1   12
1   13
1   14
1   15

来自RawData的最后30条记录的示例数据:

RawDataId, TimeStamp, BuildingId
21677   2012-05-16 00:03:00.000 1
21678   2012-05-16 00:03:00.000 1
21679   2012-05-16 00:03:00.000 1
21680   2012-05-16 00:03:00.000 1
21681   2012-05-16 00:03:00.000 1
21682   2012-05-16 00:03:00.000 1
21683   2012-05-16 00:03:00.000 1
21684   2012-05-16 00:03:00.000 1
21685   2012-05-16 00:03:00.000 1
21686   2012-05-16 00:03:00.000 1
21687   2012-05-16 00:03:00.000 1
21688   2012-05-16 00:03:00.000 1
21689   2012-05-16 00:03:00.000 1
21690   2012-05-16 00:03:00.000 1
21691   2012-05-16 00:03:00.000 1
21662   2012-05-16 00:02:00.000 1
21663   2012-05-16 00:02:00.000 1
21664   2012-05-16 00:02:00.000 1
21665   2012-05-16 00:02:00.000 1
21666   2012-05-16 00:02:00.000 1
21667   2012-05-16 00:02:00.000 1
21668   2012-05-16 00:02:00.000 1
21669   2012-05-16 00:02:00.000 1
21670   2012-05-16 00:02:00.000 1
21671   2012-05-16 00:02:00.000 1
21672   2012-05-16 00:02:00.000 1
21673   2012-05-16 00:02:00.000 1
21674   2012-05-16 00:02:00.000 1
21675   2012-05-16 00:02:00.000 1
21676   2012-05-16 00:02:00.000 1

RawDataMeter的示例:

MeterId, RawDataId, Value
15  21691   7722613
14  21690   908944
13  21689   4982947
12  21688   3821899
11  21687   6
10  21686   0
9   21685   0
8   21684   5761656
7   21683   4240048
6   21682   1541372
5   21681   283223
4   21680   1.298603E+07
3   21679   388137
2   21678   876121
1   21677   0
15  21676   7722615
14  21675   908944
13  21674   4982947
12  21673   3821899
11  21672   5
10  21671   0
9   21670   0
8   21669   5761656
7   21668   4240052
6   21667   1541372
5   21666   283223
4   21665   1.298604E+07
3   21664   388137
2   21663   876122
1   21662   0

编辑:

按照Gordon概述的步骤,我设法获得以下SQL查询,该查询似乎正常工作:

WITH 
    RawMeterData (MeterId, BuildingId, TimeStamp, LatestTimeStamp, Value) AS
(SELECT
    RawDataMeter.MeterId, 
    RawData.BuildingId, 
    RawData.TimeStamp, 
    MAX(RawData.TimeStamp) OVER (PARTITION BY BuildingMeter.BuildingMeterId) AS LatestTimeStamp, 
    RawDataMeter.Value
FROM
    BMS_RawData AS RawData
    INNER JOIN 
        BMS_RawDataMeter AS RawDataMeter 
    ON RawData.RawDataId = RawDataMeter.RawDataId
    INNER JOIN
        (SELECT 
            DISTINCT BuildingId,
            BuildingMeterId
        FROM
            AST_BuildingMeter) as BuildingMeter 
        ON RawData.BuildingId = BuildingMeter.BuildingId AND 
        RawDataMeter.MeterId = BuildingMeter.BuildingMeterId)
SELECT MeterId, BuildingId, SUM(Value) AS Value FROM RawMeterData WHERE RawMeterData.TimeStamp 
BETWEEN DATEADD(mi, -9, LatestTimeStamp) AND LatestTimeStamp
GROUP BY MeterId, BuildingId

2 个答案:

答案 0 :(得分:1)

我没有足够的时间来编写查询。

您需要执行以下操作:

  1. 在两个字段中将exists子句更改为连接。您应该在内部选择中添加“distinct”以防止重复项影响您。
  2. 使用windows函数“max(timestamp)over(partition by buildingmeterid)”来获取最新的时间戳。
  3. 将其设为子查询(或使用“with”子句)。
  4. 根据最大时间戳和时间戳之间的差异选择记录
  5. 汇总结果以获得总和。
  6. 对于编写查询,如果将别名放在所有字段名称前面会有所帮助。随便的读者无法分辨哪些字段来自哪些表格。

答案 1 :(得分:0)

这个怎么样:

select
  RawDataMeter.MeterId,
  RawDataMeter.BuildingId,
  sum(Value) as sumvalue
from
  RawData,
  RawDataMeter
where
  RawData.RawDataId=RawDataMeter.RawDataId
  RawData.TimeStamp > now() - 10*'1 minute'::interval
group by
  RawDataMeter.MeterId,
  RawDataMeter.BuildingId
order by
  RawDataMeter.MeterId,
  RawDataMeter.BuildingId

如果你的索引正确,那么这应该很快运行。此外,您在RawDataId上的表之间进行链接似乎很奇怪。我原本以为你会链接MeterId值。我希望这会有所帮助。