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

SQL-从多个表中提取集合,分组,然后求和,sql,sql-server,sql-server-2008,sql-server-2005,Sql,Sql Server,Sql Server 2008,Sql Server 2005,我需要从表RawData和RawDataMeter中提取数据,并对过去10分钟内每个唯一MeterId的“Value”字段求和(相对于时间戳)。只有在BuildingMeter表中存在RawData.BuildingId和RawDataMeter.MeterId时,才会选择使用内部联接通过RawDataId字段联接的RawData和RawDataMeter表记录。也就是说,仅当BuildingMeter表中存在RawData和RawDataMeter表中的字段时,查询才需要从中选择字段,然后需要

我需要从表RawData和RawDataMeter中提取数据,并对过去10分钟内每个唯一MeterId的“Value”字段求和(相对于时间戳)。只有在BuildingMeter表中存在RawData.BuildingId和RawDataMeter.MeterId时,才会选择使用内部联接通过RawDataId字段联接的RawData和RawDataMeter表记录。也就是说,仅当BuildingMeter表中存在RawData和RawDataMeter表中的字段时,查询才需要从中选择字段,然后需要获取每个表的最新记录(基于时间戳),然后检索该表最近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米的建筑(这是可变的)):

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
这个怎么样:

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值。我希望这有帮助。

这个怎么样:

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值。我希望这能有所帮助。

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

您需要执行以下操作:

  • 将两个字段上的exists子句更改为join。您应该在内部选择中添加一个“distinct”,以防止重复项影响您
  • 使用windows函数“max(timestamp)over(按buildingmeterid分区)”获取最近的时间戳
  • 将其作为子查询(或使用“with”子句)
  • 根据最大时间戳和时间戳之间的差异选择记录
  • 将结果聚合以获得总和

  • 在编写查询时,如果将别名放在所有字段名之前,则会有所帮助。普通读者无法分辨哪些字段来自哪些表。

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

    您需要执行以下操作:

  • 将两个字段上的exists子句更改为join。您应该在内部选择中添加一个“distinct”,以防止重复项影响您
  • 使用windows函数“max(timestamp)over(按buildingmeterid分区)”获取最近的时间戳
  • 将其作为子查询(或使用“with”子句)
  • 根据最大时间戳和时间戳之间的差异选择记录
  • 将结果聚合以获得总和

  • 在编写查询时,如果将别名放在所有字段名之前,则会有所帮助。普通读者无法分辨哪些字段来自哪些表。

    当您说最后十分钟时,这是raewdata表中最近读取的最后十分钟?如果昨天一个计价器停止工作,那么今天的结果仍然是最后十分钟?嗨,托尼。10分钟是从仪表的最新读数算起的。因此,该表将包含一组读数,它们可能来自不同的日期。当你说最后十分钟时,这是raewdata表中最近一次读数的最后十分钟?如果昨天一个计价器停止工作,那么今天的结果仍然是最后十分钟?嗨,托尼。10分钟是从仪表的最新读数算起的。因此,该表将包含混合读数,它们可能来自不同的日期。10分钟,来自仪表的最新时间戳。理论上,每一米都可能有不同的时间戳。或者可能已经停止记录值了。@Aaron Bertrand抱歉,我通常使用postgreSQL。在SQL Server中,您必须使用“fn NOW()”或“CURRENT_TIMESTAMP”或“GETDATE()”。@Dan您能解释一下为什么要在RawDataId而不是MeterId上链接表吗。如果在RawData tabl和RawDataMeter表中有一个MeterId列,那么这会容易得多。对不起,我应该澄清一下。建筑物仪表的每组结果具有相同的时间戳,但不同建筑物仪表组的时间戳(最新读数)可能不同。10分钟,来自仪表的最新时间戳。理论上,每一米都可能有不同的时间戳。或者可能已经停止记录值了。@Aaron Bertrand抱歉,我通常使用postgreSQL。在SQL Server中,您必须使用“fn NOW()”或“CURRENT_TIMESTAMP”或“GETDATE()”。@Dan您能解释一下为什么要在RawDataId而不是MeterId上链接表吗。如果在RawData tabl和RawDataMeter表中有一个MeterId列,那么这会容易得多。对不起,我应该澄清一下。建筑物仪表的每一组结果都有相同的时间戳,但不同建筑物仪表组的时间戳(最新读数)可能不同。请尝试一下。字段名称上注明的点。谢谢。我会试试这个。字段名称上注明的点。非常感谢。