繁体   English   中英

将JOIN与DISTINCT一起使用并确定一个表的优先级

[英]Using JOIN with DISTINCT and prioritize one table

我试图结合2个表的数据。
这两个表都包含来自同一传感器的数据(比方说,传感器测量二氧化碳,每10分钟输入一次)。

第一个表包含经过验证的数据。 我们称之为station1_validated 第二个表包含原始数据。 我们称之为station1_nrt

原始数据表包含实时数据,而经过验证的表仅包含至少1个月的数据点。 (它需要一些时间来验证这些数据并在之后手动控制它,这种情况每个月只发生一次)。

我现在要做的是将这两个表的数据结合起来在网站上显示实时数据。 但是,当验证数据可用时,它应该优先考虑原始数据点上的数据点。

相关的列是:

  • timed [bigint(20)]:包含日期时间作为unix时间戳,以毫秒为单位,从1.1.1970开始
  • CO2 [双倍]:包含测量的CO2浓度(ppm)(百万分率)

我写了这个基本的SQL:

SELECT 
    *
FROM
    (SELECT 
        timed, CO2, '2' tab
    FROM
        station1_nrt
    WHERE
        TIMED >= 1386932400000
            AND TIMED <= 1386939600000
            AND TIMED NOT IN (SELECT 
                timed
            FROM
                station1_nrt
            WHERE
                CO2 IS NOT NULL
                    AND TIMED >= 1386932400000
                    AND TIMED <= 1386939600000) UNION SELECT 
        timed, CO2, '1' tab
    FROM
        station1_validated
    WHERE
        CO2 IS NOT NULL
            AND TIMED >= 1386932400000
            AND TIMED <= 1386939600000) a
ORDER BY timed

这不能正常工作,因为它只选择两个表都有条目的数据点。 但是我现在想用JOIN这样做,因为它会更快。 但是,我不知道如何使用DISTINCT(或类似的东西)来加入表以确定优先级。 有人可以帮我解决这个问题(或解释一下吗?)

如果存在的记录您没有提到station1_validated不中不存在station1_nrt所以我用FULL JOIN 如果station1_validated所有行都存在于station1_nrt则可以使用LEFT JOIN。

像这样的东西

SELECT IFNULL(n.timed,v.timed) as timed,
       CASE WHEN v.timed IS NOT NULL THEN v.CO2 ELSE n.CO2 END as CO2,
       CASE WHEN v.timed IS NOT NULL THEN '1' ELSE '2' END as tab

FROM station1_nrt as n
FULL JOIN station1_validated as v ON n.timed=v.timed AND v.CO2 IS NOT NULL
    WHERE
        ( n.TIMED between 1386932400000 AND 1386939600000
          or 
          v.TIMED between 1386932400000 AND 1386939600000
        )
        AND 
        (n.CO2 IS NOT NULL OR v.CO2 IS NOT NULL)

您可以在字段中加入然后使用IF来选择已验证的值(如果存在)。 就像是:

SELECT
IFNULL(s1val.timed,s1.timed) AS timed,
IFNULL(s1val.C02,s1.C02) AS C02,
2 AS 2,
IFNULL(s1val.tab,s1.tab) AS tab,
FROM 
station1_nrt s1
LEFT JOIN station1_validated s1val ON (s1.TIMED = s1val.TIMED)
WHERE
-- Any necessary where clauses

MySQL有一个可能适合你的IF 但是,您必须选择特定列,但可以通过编程方式构建查询。

SELECT
    IF(DATE_SUB(NOW(), INTERVAL 1 MONTH) < FROM_UNIXTIME(nrt.TIMED),
        val.value,
        nrt.value
    ) AS value
    -- Similar for other values
FROM
    station1_nrt AS nrt
    JOIN station1_validated AS val USING(id)
ORDER BY TIMED

请注意, USING(id)是占位符。 据推测,有一些索引列可以加入这两个表。

@Jim,@valex,@ ExplosionPills我设法编写了一个模拟FULL OUTER JOIN的SQL选择(因为MySQL中没有FULL JOIN)并返回验证数据的值(如果存在)。 如果没有可用的验证数据,它将返回原始值

所以这就是我现在使用的SQL:

SET @StartTime  = 1356998400000;
SET @EndTime    = 1386546000000;

SELECT
    timed,
    IFNULL (mergedData.validatedValue, mergedData.rawValue) as value
FROM
((SELECT 
    from_unixtime(timed / 1000) as timed,
    rawData.NOX as rawValue,
    validatedData.NOX as validatedValue
FROM
    nabelnrt_bas as rawData
    LEFT JOIN nabelvalidated_bas as validatedData using(timed)
WHERE 
    (rawData.timed > @StartTime
    AND rawData.timed < @EndTime)
    OR (validatedData.timed > @StartTime
    AND validatedData.timed < @EndTime)

) UNION (
SELECT 
    from_unixtime(timed / 1000) as timed,
    rawData.NOX as rawValue,
    validatedData.NOX as validatedValue
FROM
    nabelnrt_bas as rawData
    RIGHT JOIN nabelvalidated_bas as validatedData using(timed)
WHERE 
    (rawData.timed > @StartTime
    AND rawData.timed < @EndTime)
    OR (validatedData.timed > @StartTime
    AND validatedData.timed < @EndTime)
)
ORDER BY timed DESC) as mergedData

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM