我有一个如下的MySQL表。 id
和name
字段仅用于帮助识别行,l
代表许多其他字段,而不是相关数据,并使用lat
和lng
找到重复的条目。
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
答案 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
;
答案 1 :(得分:0)
您是否有能力改变架构?最好将该名称列标准化为几列:而不是
id | lat | lng | l | name
你的专栏应该是
id | lat | lng | l | groupOrSingle | groupid | memberid
然后编写查询将是微不足道的,更不用说更有效地运行方式,因为您可以索引要查询的分组信息。