MySQL使用中间表检索值

bnl4lu3b  于 2023-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(101)

我有以下表格:
猴子:
| id|姓名|
| - -----|- -----|
| 1|约翰|
| 2|玛丽|
检查:
| id|猴ID|支票日期|
| - -----|- -----|- -----|
| 1| 1| 2023 - 06 - 02 03:00:00|
| 2| 2| 2023 - 08 - 24 14:30:00|
| 3| 1| 2023 - 06 - 04 14:35:00|
测量:
| id|检查ID|长度|宽度|重量|
| - -----|- -----|- -----|- -----|- -----|
| 1| 1|二十三点三十四分|六点三四|3.2|
| 2| 1|二十三点八七|6.22|空值|
| 3| 1|二十四点三|6.10|空值|
| 4| 2|二十七点八|7.4|空值|
| 5个|2|二十七点五六|七点六二|空值|
XMITTER:
| id|检查ID|渠道|调|附加启动|附着整理|移除|
| - -----|- -----|- -----|- -----|- -----|- -----|- -----|
| 1| 3|五三四|2| 2023 - 08 - 24 14:30:32| 2023 - 08 - 24 14:45:00|空值|
| 2| 1|五三二|1| 2023 - 06 - 02 03:31:00| 2023 - 06 - 02 03:35:00| 2023 - 06 - 10 14:45:00|
我该如何找回猴子:
1.最近一次检查日期
1.同时进行多组长度/宽度测量(并通过check_id连接)-我想返回最近的长度/宽度测量和重量的平均值,通常在检查期间只进行一次。
1.当前变送器(如果已连接)。如果没有拆除日期,则连接发送器。
示例结果集:
| monkey.id | 最后检查日期|最新平均长度|最新平均宽度|最新平均宽度|渠道|调|通道连接启动|
| - -----|- -----|- -----|- -----|- -----|- -----|- -----|- -----|
| 1| 2023 - 06 - 04 2023 - 06 - 04|二十三点八二|六点二十|3.2|五三二|1| 2023 - 06 - 02 2023 - 06 - 02|
每只猴子应有一个结果集。
我在这里创建了一个小提琴-这是相同的结构(略有不同的数据)。

  • 注意:最近的测量值在检查1上。最近的xmitter位于检查3上。
chhkpiq4

chhkpiq41#

此查询假设:
1.每只猴子至少有一个health_check和一组measurements
1.每只猴子只能有一个或零个发射器
让我们从获取最新的health_check开始。由于idhealth_check_date不是按顺序排列的,我们需要获得每个monkey_id``health_check_date,然后连接回health_check表以获得id,然后连接到measurements。对于(monkey_id, health_check_date)上的索引,内部查询不需要从聚集索引读取:

SELECT
    hc.monkey_id,
    hc_max.last_check_date,
    AVG(length) AS newest_avg_length,
    AVG(width) AS newest_avg_width,
    AVG(weight) AS newest_avg_weight
FROM health_check hc
JOIN (
    SELECT monkey_id, MAX(health_check_date) AS last_check_date
    FROM health_check
    -- WHERE monkey_id = 2 /* Uncomment this line if for specific monkey */
    GROUP BY monkey_id
) hc_max
    ON hc.monkey_id = hc_max.monkey_id
    AND hc.health_check_date = hc_max.last_check_date
JOIN measurements ms
    ON hc.id = ms.health_check_id
GROUP BY hc.monkey_id;

您可以使用窗口函数实现相同的功能,但它会带来更大的开销。我将此作为一个选项,以便您可以根据您的数据对其进行测试:

SELECT
    monkey_id,
    health_check_date AS last_check_date,
    AVG(length) AS newest_avg_length,
    AVG(width)  AS newest_avg_width,
    AVG(weight) AS newest_avg_weight
FROM (    
    SELECT hc.*, ROW_NUMBER() OVER (PARTITION BY hc.monkey_id ORDER BY hc.health_check_date DESC) rn
    FROM health_check hc
) x
JOIN measurements m ON x.id = m.health_check_id
WHERE rn = 1
GROUP BY x.id;

使用上述查询之一作为派生表,然后可以通过health_checkLEFT JOINtransmitter,以获取当前tx。

SELECT
    latest_health_check.monkey_id,
    latest_health_check.last_check_date,
    latest_health_check.newest_avg_length,
    latest_health_check.newest_avg_width,
    latest_health_check.newest_avg_weight,
    tx.channel,
    tx.offset,
    DATE(tx.attach_start) AS channel_attach_start
FROM (
    -- Derived table for the latest check.
    SELECT
        hc.monkey_id,
        hc_max.last_check_date,
        AVG(length) AS newest_avg_length,
        AVG(width) AS newest_avg_width,
        AVG(weight) AS newest_avg_weight
    FROM health_check hc
    JOIN (
        SELECT monkey_id, MAX(health_check_date) AS last_check_date
        FROM health_check
        -- WHERE monkey_id = 2 /* Uncomment this line if for specific monkey */
        GROUP BY monkey_id
    ) hc_max
        ON hc.monkey_id = hc_max.monkey_id
        AND hc.health_check_date = hc_max.last_check_date
    JOIN measurements ms
        ON hc.id = ms.health_check_id
    GROUP BY hc.monkey_id
) latest_health_check
LEFT JOIN transmitter tx
    ON EXISTS (
        SELECT 1 FROM health_check hc
        WHERE hc.id = tx.health_check_id
        AND hc.monkey_id = latest_health_check.monkey_id
    )
    AND tx.removed IS NULL;

这是你的小提琴的升级版
P.S.它只返回monkey_id 2,因为这是唯一一只在最近一次检查中有测量值的猴子。

zhte4eai

zhte4eai2#

SELECT
  m.id AS monkey_id,
  MAX(h.health_check_date) AS last_check_date,
  AVG(me.length) AS newest_average_length,
  AVG(me.width) AS newest_average_width,
  AVG(me.weight) AS newest_avg_weight,
  t.channel AS channel,
  t.offset AS tune,
  t.attach_start AS channel_attach_start
FROM
  monkeys m
 JOIN
  health_check h ON h.monkey_id = m.id
 JOIN
  measurements me ON me.health_check_id = h.id
 JOIN
  transmitter t ON t.health_check_id = h.id AND t.removed IS NULL

GROUP BY
  m.id, m.name
ORDER BY
  m.id;

相关问题