具有AND匹配功能的多列IN SELECT

时间:2014-11-25 14:02:58

标签: mysql vb.net

我有两张桌子,在第一张桌子上我有一个设备列表,上面有他们的ID,帐号以及设备更新自己状态的最后一个时间戳。这张表很小,有大约50K行。

在第二张表格中,我收到了所有设备的所有报告。这张桌很重,此时此刻有大约200.000.000(200万)行。

大表有三个PK列accountID,deviceID和timestamp

我正在从VB.NET应用程序进行查询

从第一个小表中我得到一个带有最后一个时间戳的deviceID列表,以便进行查询,从而更快地在大表上获得一些行。

我面临的问题是我得到了一些我不需要的数据。

示例:

 accountID deviceID  timestamp
     1       A         23
     1       A         24
     1       A         25
     1       B         23

所以,如果我想获得带有最后一个时间戳的行

SELECT* FROM clients.Events
WHERE timestamp IN ('25','23')
AND deviceID IN ('A','B')
AND accountID IN ('1')

我得到了

 accountID deviceID  timestamp
     1       A         23
     1       A         25
     1       B         23

我需要

 accountID deviceID  timestamp
     1       A         25
     1       B         23

那么,有没有办法将时间戳与deviceID相匹配?

我知道我可以使用MAX子句但是,正如我之前所说,事件基数很大,我需要尽可能快的结果和MAX子句检查整个表并花费太多时间。

大型活动表是InnoDB。

DDL

CREATE TABLE `Events` (
    `accountID` varchar(32) NOT NULL,
    `deviceID` varchar(32) NOT NULL,
    `timestamp` int(10) unsigned NOT NULL,
    `statusCode` int(10) unsigned NOT NULL,
    `latitude` double DEFAULT NULL,
    `longitude` double DEFAULT NULL,
    `gpsAge` int(10) unsigned DEFAULT NULL,
    `speedKPH` double DEFAULT NULL,
    `heading` double DEFAULT NULL,
    `altitude` double DEFAULT NULL,
    `transportID` varchar(32) DEFAULT NULL,
    `inputMask` int(10) unsigned DEFAULT NULL,
    `outputMask` int(10) unsigned DEFAULT NULL,
    `address` varchar(90)CHARACTER SET utf8 DEFAULT NULL,
    `dataSource` varchar(32) DEFAULT NULL,
    `rawData` text,
    `distanceKM` double DEFAULT NULL,
    `odometerKM` double DEFAULT NULL,
    `geozoneIndex` int(10) unsigned DEFAULT NULL,
    `geozoneID` varchar(32) DEFAULT NULL,
    `creationTime` int(10) unsigned DEFAULT NULL,
    `streetAddress` varchar(90)CHARACTER SET utf8 DEFAULT NULL,
    `city` varchar(40)CHARACTER SET utf8 DEFAULT NULL,
    `stateProvince` varchar(40)CHARACTER SET utf8 DEFAULT NULL,
    `postalCode` varchar(16)CHARACTER SET utf8 DEFAULT NULL,
    `country` varchar(40)CHARACTER SET utf8 DEFAULT NULL,
    `subdivision` varchar(32)CHARACTER SET utf8 DEFAULT NULL,
    `speedLimitKPH` double DEFAULT NULL,
    `isTollRoad` tinyint(4) DEFAULT NULL,
    `gpsFixType` smallint(5) unsigned DEFAULT NULL,
    `horzAccuracy` double DEFAULT NULL,
    `vertAccuracy` double DEFAULT NULL,
    `HDOP` double DEFAULT NULL,
    `satelliteCount` smallint(5) unsigned DEFAULT NULL,
    `batteryLevel` double DEFAULT NULL,
    `batteryVolts` double DEFAULT NULL,
    `signalStrength` double DEFAULT NULL,
    PRIMARY KEY (`accountID` , `deviceID` , `timestamp` , `statusCode`)
)  ENGINE=InnoDB DEFAULT CHARSET=latin1

1 个答案:

答案 0 :(得分:0)

SELECT CE.*
FROM clients.events CE
INNER JOIN (SELECT accountID, DeviceID, Max(timestamp) TS 
            FROM clients.events 
            GROUP YB accountID, DeviceID) CE2
  on CE.AccountID=CE2.accountId
 and CE.DeviceID= CE2.DeviceID
 and CE.TimeStamp = CE2.TS

上面的内容为您提供每个设备和帐户的最大时间戳记录 现在你只需要过滤......

WHERE DeviceID in ('A','B') and accountID = '1' and timestamp in ('25','23')

使用适当的索引应该有效地工作。