我写了这个查询,它几乎完成了我想要的事情:
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)有两个日期时间列:'begin'和'end'。我需要这两列的值在3天之内才能满足GROUP_CONCAT条件。
编辑:为了将电台包含在最终结果的GROUP_CONCAT中,它必须满足以下条件:
它必须与列表中的另一个站位于同一位置(group by 纬度,经度,海拔)
其end
时间必须在另一个电台begin
时间的3天内或其begin
时间必须在另一个电台的3天内
{{1次。当我说“另一个电台”时,我指的是电台
它们位于同一地点(符合#1的条件)。
我认为我将不得不使用子查询,但我似乎无法弄清楚如何做到这一点。一些帮助将不胜感激!查询或存储过程都很棒但是php解决方案也是可以接受的。
以下是我要查询的表的转储:sql dump
结果应该与我的示例相同,但非相邻项目(按日期)不应该在那里。
答案 0 :(得分:1)
我只有SQL Server的访问权限和知识,所以我无法让你的数据工作,我不知道MySQL是否具有相同的功能,但这里是对你需要做什么的口头描述。
你需要一个递归语句(在SQL Server中使用CTE)将表连接到lat,lon,elev上,并开始BETWEEN结束-3和结束+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
答案 1 :(得分:1)
解决方案可能是使用子查询在3天内计算站点列表,并将此子查询作为where子句添加到主查询中。
子查询包含一个笛卡尔积,用于列出所有可能的站对,其中第一个条件只能得到结果矩阵的前半部分,两个条件用于指定时间约束。关于后面的这些条件,我猜对了,我真的不知道begin
和end
字段的度量单位。
生成的查询可能是:
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;