0

我有以下 SQL:

SELECT devices.device_id,
   devices.description,
   sensors.sensor_id,
   sensors.description,
   measurements.value,
   measurements.valueDate,
   measurements.created_at
FROM measurements
INNER JOIN sensors
   ON sensors.id = measurements.sensor_id
INNER JOIN devices
   ON devices.id = sensors.device_id
WHERE devices.device_id = '123456'
   AND sensors.sensor_id = '100102'
   AND measurements.created_at < (
      SELECT created_at
      FROM measurements
      ORDER BY created_at DESC LIMIT 1
      )
   AND measurements.created_at > DATE_ADD((
         SELECT created_at
         FROM measurements
         ORDER BY created_at DESC LIMIT 1
         ), INTERVAL - 48 DAY)

我相信问题出在最后两行......我想检索从引用内部连接表而不是整个测量表的日期起的最后 48 天。我不知道如何引用属于连接表结果的列。我应该给连接表起别名吗?

这些表是:

Devices
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `device_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `country_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `city` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

Sensors
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `device_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `sensor_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `state` tinyint(1) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

Mesurements
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `sensor_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `valueDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  `value` float(8,2) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
4

1 回答 1

1

可能的解决方案:

SELECT devices.device_id,
       devices.description,
       sensors.sensor_id,
       sensors.description,
       m.value,
       m.valueDate,
       m.created_at
FROM (
   SELECT max( m.created_at ) max_date,
          max( m.created_at ) - interval 48 day min_date
   FROM measurements m
   INNER JOIN sensors
      ON sensors.id = m.sensor_id
   INNER JOIN devices
      ON devices.id = sensors.device_id
   WHERE devices.device_id = '123456'
      AND sensors.sensor_id = '100102'
) q
JOIN measurements m
ON m.created_at BETWEEN q.min_date AND q.max_date
INNER JOIN sensors
      ON sensors.id = m.sensor_id
INNER JOIN devices
      ON devices.id = sensors.device_id
WHERE devices.device_id = '123456'
      AND sensors.sensor_id = '100102'

演示:http ://www.sqlfiddle.com/#!2/73a5d/3


一些备注:

该查询使用以下比较连接表:

  • ON 传感器.id = 测量值.sensor_id
  • ON devices.id = 传感器.device_id

值得一提的是:

  • sensors.id是类型的int(10)measurements.sensor_id而是类型的varchar(255)
  • devices.id是类型的int(10)sensors.device_id而是类型的varchar(255)

表结构的设计存在缺陷,需要重新设计,这可能是一首歌曲。这会影响性能,因为 MySql 必须不断地执行从字符串到数字的转换(反之亦然)。

于 2013-10-26T13:59:09.830 回答