1

我有一个如下的 MySQL 表。和字段只是在这里帮助识别行,代表许多其他不相关数据的字段,并用于id查找重复条目。namellatlng

CREATE TABLE v
    (`id` int, `lat` int, `lng` int, `l` varchar(3), `name` varchar(8))
;

INSERT INTO v
    (`id`, `lat`, `lng`, `l`, `name`)
VALUES
    ( 1, 12, 12, 'a', 'group1-1'),
    ( 2, 12, 12, 'b', 'group1-2'),
    ( 3, 13, 12, 'c', 'single1'),
    ( 4, 13, 13, 'd', 'group2-1'),
    ( 5, 13, 13, 'e', 'group2-2'),
    ( 6, 13, 13, 'f', 'group2-3'),
    ( 7, 10, 13, 'g', 'group3-1'),
    ( 8, 10, 13, 'h', 'group3-2'),
    ( 9, 11, 12, 'h', 'group4-1'),
    (10, 11, 12, 'h', 'group4-2'),
    (11, 10, 14, 'i', 'group5-1'),
    (12, 10, 14, 'j', 'group5-2'),
    (13, 10, 14, 'j', 'group5-3')
;

现在我想获取所有行,其中有多个具有相同 lat 和 lng 值的行(我们称其为组):

SELECT v.*
FROM v
 INNER JOIN (
  SELECT lat, lng
  FROM v
  GROUP BY lat, lng
  HAVING COUNT(*) > 1
  ) AS vg
  USING (lat, lng)
ORDER BY name
;

输出:

ID  LAT LNG L   NAME
1   12  12  a   group1-1
2   12  12  b   group1-2
4   13  13  d   group2-1
5   13  13  e   group2-2
6   13  13  f   group2-3
7   10  13  g   group3-1
8   10  13  h   group3-2
9   11  12  h   group4-1
10  11  12  h   group4-2
11  10  14  i   group5-1
12  10  14  j   group5-2
13  10  14  j   group5-3

到目前为止效果很好,除了“single1”之外的所有行都按组选择和排序。

现在我想添加一个限制来形成这个数据的不同页面。但是同一组的所有行都需要在同一页上(但不是每组一页,一页上实际有多少行并不重要——只是不要太多)。我没有看到使用 LIMIT 语句完成此操作,所以我开始编写自己的:

SET @grp := 0, @last_lat := '', @last_lng := '';

SELECT * FROM (
 SELECT v.*,
  @grp := IF((@last_lat = lat) && (@last_lng = lng), @grp, @grp + 1) AS grp,
  @last_lat := lat AS llat,
  @last_lng := lng AS llng
 FROM v
  INNER JOIN (
   SELECT lat, lng
   FROM v
   GROUP BY lat, lng
   HAVING COUNT(*) > 1
   ) AS vg
   USING (lat, lng) 
 ORDER BY lat, lng
) AS vv
WHERE grp BETWEEN 0 AND 7
ORDER BY grp
;

这个查询没有 WHERE 部分输出这个数据:

ID  LAT LNG L   NAME        GRP LLAT    LLNG
1   12  12  a   group1-1    6   12  12
2   12  12  b   group1-2    6   12  12
5   13  13  e   group2-2    7   13  13
6   13  13  f   group2-3    7   13  13
4   13  13  d   group2-1    7   13  13
7   10  13  g   group3-1    8   10  13
8   10  13  h   group3-2    8   10  13
10  11  12  h   group4-2    9   11  12
9   11  12  h   group4-1    9   11  12
13  10  14  j   group5-3    10  10  14
11  10  14  i   group5-1    10  10  14
12  10  14  j   group5-2    10  10  14

想法是更改每页的 WHERE grp BETWEEN 0 AND 7 行中的值。但是该组的数字不是从 1 开始的,我不明白为什么(这使得它无法用于第一页)。起始编号因整个数据中有多少组而异。所以我需要的是,grp 列从 1 开始,然后始终以 +1 继续。

这个查询有什么问题,有没有更好的方法来做到这一点?

你可以在这里玩这个查询:http ://sqlfiddle.com/#!8/86d3c/2

4

2 回答 2

1
SET @grp := 0, @last_lat := '', @last_lng := '';

SELECT vv.*,@grp-grp+1 as orgGrp FROM (
 SELECT v.*,
  @grp := IF((@last_lat = lat) && (@last_lng = lng), @grp, @grp + 1) AS grp,
  @last_lat := lat AS llat,
  @last_lng := lng AS llng
 FROM v
  INNER JOIN (
   SELECT lat, lng
   FROM v
   GROUP BY lat, lng
   HAVING COUNT(*) > 1
   ) AS vg
   USING (lat, lng) 
 ORDER BY lat, lng
) AS vv

ORDER BY orgGrp
;

SQLFIDDLE

于 2013-05-16T07:31:44.950 回答
0

你有能力改变架构吗?您最好将该名称列规范化为几列:而不是

id | lat | lng | l | name

你的列应该是

id | lat | lng | l | groupOrSingle | groupid | memberid

然后编写查询将是微不足道的,更不用说更有效的运行方式,因为您将能够索引您正在查询的分组信息。

于 2013-05-15T18:52:21.547 回答