MySQL:按一组行限制,而不是按一行限制
我有一个如下所示的MySQL表。MySQL:按一组行限制,而不是按一行限制,mysql,sql,Mysql,Sql,我有一个如下所示的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'),
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值的所有行(我们称之为组):
产出:
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”行之外,所有行都是按组选择和排序的
现在我想添加一个限制,以形成此数据的不同页面。但同一组的所有行都需要在同一页上(但不是每个组一页,一页上实际有多少行并不重要,只是不要太多)。我不认为用限制语句就能做到这一点,所以我开始写我自己的:
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
;
此查询将显示零件输出此数据的位置:
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
我们的想法是更改grp所在行中的值,每个页面的grp介于0和7之间。但是组中的数字不是从1开始的,我也不明白为什么(这使得它无法用于第一页)。根据整个数据中有多少组,起始编号是不同的。所以我需要的是,grp列从1开始,然后一直到+1
这个查询有什么问题,有没有更好的方法
你可以在这里玩这个查询:你有能力改变模式吗?最好将该名称列规范化为几列:而不是
id | lat | lng | l | name
你的专栏应该是
id | lat | lng | l | groupOrSingle | groupid | memberid
那么,编写查询就很简单了,更不用说运行方式了,因为您可以为正在查询的分组信息编制索引。您有能力更改模式吗?最好将该名称列规范化为几列:而不是
id | lat | lng | l | name
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
;
你的专栏应该是
id | lat | lng | l | groupOrSingle | groupid | memberid
然后编写查询将是一件小事,更不用说运行方式了,因为您将能够索引您正在查询的分组信息
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
;
你能根据样本数据发布预期结果吗?@PM77-1我添加了输出和一些解释。你能根据样本数据发布预期结果吗?@PM77-1我添加了输出和一些解释。不,我不能更改架构。这些组实际上并不是我想要的-我通过这个查询来搜索应该被修复的错误条目。此外,这里的名称只是为了更容易看到它是哪些数据。在真实的数据中,它们是不同的,与任何组都无关。不,我不能更改模式。这些组实际上并不是我想要的-我通过这个查询来搜索应该被修复的错误条目。此外,这里的名称只是为了更容易看到它是哪些数据。在实际数据中,它们与任何组都不同且无关。如果您的组始终有5列,则初始化@grp:=-5。。这会起作用的,因为小组的规模总是不同的。但是你的查询无法工作。你能解释一下它是怎么工作的吗?谢谢在这个-fiddle中,子查询首先执行,结果是一组5个。当您从“vv”中选择时,将再次检查条件,如果lat和lng与前一个不同,将添加1。如果您能够从子查询中初始化max(组号)的负数,则可以完成此操作。如果您的组始终有5列,则初始化@grp:=-5。。这会起作用的,因为小组的规模总是不同的。但是你的查询无法工作。你能解释一下它是怎么工作的吗?谢谢在这个-fiddle中,子查询首先执行,结果是一组5个。当您从“vv”中选择时,将再次检查条件,如果lat和lng与前一个不同,将添加1。如果您能够从子查询中初始化max(组号)的负数,那么它将完成此任务。