MySQL:限制一组行,而不是一行

时间:2013-05-15 15:34:07

标签: mysql sql

我有一个如下的MySQL表。 idname字段仅用于帮助识别行,l代表许多其他字段,而不是相关数据,并使用latlng找到重复的条目。

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和7行中的值。但该组中的数字不是从1开始,我看不出原因(这使得第一页无法使用)。起始编号因整个数据中的组数而异。所以我需要的是,grp列从whit 1开始然后继续whit始终+1。

此查询有什么问题,还有更好的方法吗?

您可以在此处播放此查询:http://sqlfiddle.com/#!8/86d3c/2

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

您是否有能力改变架构?最好将该名称列标准化为几列:而不是

id | lat | lng | l | name

你的专栏应该是

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

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