1

我写了这个查询,它几乎做了我想要的:

SELECT * FROM 
(
   SELECT COUNT(*) as cnt,
   lat,
   lon,
   elev, 
   GROUP_CONCAT(CONCAT(usaf,'-',wban))
   FROM `ISH-HISTORY_HASPOS` 
   GROUP BY  lat,lon,elev 
 ) AS x WHERE cnt >=1;

输出:

+-----+--------+----------+--------+-------------------------------------------------+
| cnt | lat    | lon      | elev   | GROUP_CONCAT(CONCAT(usaf,'-',wban))                              |
+-----+--------+----------+--------+-------------------------------------------------+
|   4 | 30.478 |  -87.187 | 36     | 722220-13899,722221-13899,722223-13899,999999-13899              |
|   4 | 36.134 |  -80.222 | 295.7  | 723190-93807,723191-93807,723193-93807,999999-93807              |
|   5 | 37.087 |  -84.077 | 369.1  | 723290-03849,723291-03849,723293-03849,724243-03849,999999-03849 |
|   5 | 38.417 | -113.017 | 1534.1 | 745200-23176,745201-23176,999999-23176,724757-23176,724797-23176 |
|   4 | 40.217 |  -76.851 | 105.8  | 999999-14751,725110-14751,725111-14751,725118-14751              |
+-----+--------+----------+--------+-------------------------------------------------+

这将返回位于相同坐标的站点的串联列表。但是,我只对连接具有相邻日期范围的电台感兴趣。我从 (ISH-HISTORY_HASPOS) 中选择的表有两个日期时间列:“开始”和“结束”。我需要这两列的值在 3 天内彼此满足 GROUP_CONCAT 条件。

编辑:为了使站包含在最终结果的 GROUP_CONCAT 中,它必须满足以下条件:

  1. 它必须与列表中的另一个站点位于同一位置(按纬度、经度、海拔分组)

  2. 它的end时间必须在另一个站的begin时间的 3 天内,或者它的begin时间必须在另一个站的 end时间的 3 天内。当我说“另一个车站”时,我指的是位于同一地点的车站(满足#1 的条件)。

我想我将不得不使用子查询,但我似乎无法弄清楚如何去做。一些帮助将不胜感激!查询或存储过程都很好,但 php 解决方案也可以接受。

这是我正在查询的表的转储:sql dump

结果应该与我的示例相同,但不应该存在非相邻项目(按日期)。

4

2 回答 2

1

我只有 SQL Server 的访问权限和知识,所以我无法让您的数据正常工作,我不知道 MySQL 是否具有等效功能,但这里是您需要做什么的口头描述。

您需要一个递归语句(在 SQL Server 中使用 CTE)以在 lat、lon、elev 上将表连接到自身,并在 end -3 和 end +3 之间开始。您需要小心不要陷入无限循环 - 我建议您构建一个逗号分隔的列表,列出您访问过的 ID,并随时检查。这很痛苦,但请按照 ID 顺序保留此列表,因为这是您最后需要分组的内容。您还需要跟踪您的深度和原始 ID。

就像是 ...

WITH cte(id, idlist, lat, lon, elev, starts, ends)
AS (
SELECT id, CAST(id AS varchar), lat, lon, elev, starts, ends
FROM `ISH-HISTORY_HASPOS`
UNION ALL
SELECT i.id, FunctionToManagetheList(i.idlist, cte.id), lat, lon, elev, starts, ends
FROM `ISH-HISTORY_HASPOS` i
     INNER JOIN
     cte ON i.lat=cte.lat AND 
            i.lon=cte.lon AND 
            i.elev=cte.elev AND
            NOT FunctionToCheckIfTheIDisintheLitst(i.id, cte.idlist)
)
SELECT stuffyouneed
FROM   `ISH-HISTORY_HASPOS` i
       INNER JOIN
       (SELECT id, MAX(depth) AS MaxDepth
       FROM    cte 
       GROUP BY id) cte1 ON i.id=cte.id
       INNER JOIN
       cte cte2 ON cte1.id=cte2.id AND cte1.MaxDepth=cte2.Depth
GROUP BY cte.idlist
于 2012-12-03T05:36:27.597 回答
1

一种解决方案可能是使用子查询来计算彼此相隔 3 天内的站点列表,并将此子查询作为 where 子句添加到主查询中。子查询由一个笛卡尔积组成,用于列出所有可能的站对,第一个条件仅获得结果矩阵的前半部分,两个条件指定时间约束。至于后面的这些条件我只是猜到了,我真的不知道beginandend字段的度量单位。结果查询可能是这样的:

SELECT * FROM (
    SELECT COUNT(*) AS
       cnt,
       lat,
       lon,
       elev,
    GROUP_CONCAT(CONCAT(usaf, '-', wban))  
    FROM ISH-HISTORY_HASPOS  
    WHERE id IN (
        SELECT DISTINCT t1.id  
        FROM ISH-HISTORY_HASPOS t1  
        INNER JOIN ISH-HISTORY_HASPOS t2
           ON t1.lon = t2.lon
           AND t1.lat = t2.lat
           AND t1.elev = t2.elev  
        WHERE t1.id < t2.id
            AND abs(t1.begin - t2.end) < 259200
            AND abs(t1.end - t2.begin) < 259200  
        UNION  
        SELECT DISTINCT t2.id  
        FROM ISH-HISTORY_HASPOS t1  
        INNER JOIN ISH-HISTORY_HASPOS t2
            ON t1.lon = t2.lon
            AND t1.lat = t2.lat
            AND t1.elev = t2.elev  
        WHERE t1.id < t2.id
            AND abs(t1.begin - t2.end) < 259200
            AND abs(t1.end - t2.begin) < 259200
    )
    GROUP BY lat, lon, elev   
) AS x WHERE cnt >= 1;
于 2012-12-03T08:02:02.590 回答