如何获得4个不同值的ID(2个键的组合)

时间:2017-01-30 09:08:46

标签: mysql sql mariadb

我得到了如下表格

mysql> select * from tb_dts;
+----+------+------+
| Id | key1 | key2 |
+----+------+------+
|  1 |    1 |    1 |
|  2 |    1 |    1 |
|  3 |    1 |    1 |
|  4 |    2 |    1 |
|  5 |    2 |    1 |
|  6 |    2 |    1 |
|  7 |    2 |    1 |
|  8 |    1 |    2 |
|  9 |    1 |    2 |
| 10 |    1 |    2 |
| 11 |    1 |    2 |
| 12 |    1 |    2 |
| 13 |    3 |    1 |
| 14 |    3 |    1 |
| 15 |    3 |    1 |
| 16 |    3 |    1 |
| 17 |    2 |    2 |
| 18 |    2 |    2 |
| 19 |    2 |    2 |
| 20 |    2 |    3 |
| 21 |    2 |    3 |
| 22 |    2 |    3 |
| 23 |    3 |    2 |
| 24 |    3 |    2 |
| 25 |    3 |    2 |
| 26 |    3 |    2 |
+----+------+------+
26 rows in set (0.00 sec)

我采用了这样的不同值,用于某些应用程序分页

mysql> select distinct key1,key2 from tb_dts limit 0,4;
+------+------+
| key1 | key2 |
+------+------+
|    1 |    1 |
|    1 |    2 |
|    2 |    1 |
|    2 |    2 |
+------+------+
4 rows in set (0.00 sec)

mysql> select distinct key1,key2 from tb_dts limit 4,4;
+------+------+
| key1 | key2 |
+------+------+
|    2 |    3 |
|    3 |    1 |
|    3 |    2 |
+------+------+
3 rows in set (0.00 sec)

通过group_concat我也得到了ID,但我想在WHERE Field IN子句where somefield IN ( ..here my Ids goes...)

中使用此ID
mysql> select key1,key2,group_concat(Id) from tb_dts group by key1,key2 limit 0,4;
+------+------+------------------+
| key1 | key2 | group_concat(Id) |
+------+------+------------------+
|    1 |    1 | 1,2,3            |
|    1 |    2 | 8,9,10,11,12     |
|    2 |    1 | 4,5,6,7          |
|    2 |    2 | 17,18,19         |
+------+------+------------------+
4 rows in set (0.00 sec)

mysql> select key1,key2,group_concat(Id) from tb_dts group by key1,key2 limit 4,4;
+------+------+------------------+
| key1 | key2 | group_concat(Id) |
+------+------+------------------+
|    2 |    3 | 20,21,22         |
|    3 |    1 | 13,14,15,16      |
|    3 |    2 | 23,24,25,26      |
+------+------+------------------+
3 rows in set (0.00 sec)

但是我如何将它放在WHERE Fieldname IN条款中?

我需要这样的内容,因为我的tb_dts包含更多 3000万 reocrds和15字段,我无法使用{{1 }}

要处理我需要的前4个唯一组合值

ID BETWEEN min_id and max_id

为了处理接下来的4个唯一组合值,我需要在我的应用程序中使用ID,所以简而言之,我想在我的select * from tb_dts where Id IN (1,2,3,8,9,10,11,12,4,5,6,7,17,18,19 ) 子句中提到下面提到的ID

where Field IN

这是我表的结构

select * from tb_dts where Id IN (20,21,22,13,14,15,16,23,24,25,26 )

正如您在此处所见,它为每个不同的组合值提供了第一个找到的ID

DROP TABLE IF EXISTS `tb_dts`;
CREATE TABLE `tb_dts` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `key1` int(11) DEFAULT '-99',
  `key2` int(11) DEFAULT '-99',
  PRIMARY KEY (`Id`),
  KEY `main` (`key1`,`key2`)
) ENGINE=MyISAM AUTO_INCREMENT=27 DEFAULT CHARSET=latin1;

LOCK TABLES `tb_dts` WRITE;
INSERT INTO `tb_dts` VALUES (1,1,1),(2,1,1),(3,1,1),(4,2,1),(5,2,1),(6,2,1),(7,2,1),(8,1,2),(9,1,2),(10,1,2),(11,1,2),(12,1,2),(13,3,1),(14,3,1),(15,3,1),(16,3,1),(17,2,2),(18,2,2),(19,2,2),(20,2,3),(21,2,3),(22,2,3),(23,3,2),(24,3,2),(25,3,2),(26,3,2);
UNLOCK TABLES;

但我希望所有mysql> select Id from tb_dts group by key1,key2 limit 0,4; +----+ | Id | +----+ | 1 | | 8 | | 4 | | 17 | +----+ 4 rows in set (0.00 sec) 都符合给定的标准,这只不过是所有ID低于4的唯一值

Ids

预期o / p

对于mysql> select key1,key2 from tb_dts group by key1,key2 limit 0,4; +------+------+ | key1 | key2 | +------+------+ | 1 | 1 | --- 1,2,3 | 1 | 2 | --- 8,9,10,11,12 | 2 | 1 | --- 4,5,6,7 | 2 | 2 | --- 17,18,19 +------+------+ 4 rows in set (0.00 sec) ,我希望得到Id这样的内容,以便可以在我的group by key1,key2 limit 0,4子句中使用。

WHERE IN

4 个答案:

答案 0 :(得分:1)

对于您的直接问题,您可以使用find_in_set,如下所示:

select t.*
from your_table t
where exists (
    select 1 from (
        select group_concat(Id)
        from tb_dts
        group by key1, key2
        order by key1, key2   -- very important when using limit
        limit 0, 4
    ) t2 where find_in_set(t.fieldname, t2.ids) > 0
);

虽然我不确定这是否是做你正在做的事情的最佳方式。使用group by创建字符串然后在该字符串中搜索将太慢。

此外,您希望在key1,key2,id列上有索引。

create index idx_tb_dts on tb_dts (key1, key2, id);

可以试试这个:

select t.*
from your_table t
where exists (
    select 1
    from tb_dts t1
    inner join (
        select distinct key1, key2
        from tb_dts
        order by key1, key2
        limit 0, 4
    ) t2 on t1.key1 = t2.key1
    and t1.key2 = t2.key2
    where t1.id = t.fieldname
);

你应该明白,群体或不同部分的表现可能很重要。如果有一个单独的表包含唯一的key1,key2,并且它们具有唯一索引,那将会好得多。

create table the_keys_table(
    key1 int not null,
    key2 int not null,
    primary key (key1, key2)
);

然后你可以用这个表替换下面的tb_dts:

select key1, key2       -- no distinct or group by needed.
from the_keys_table
order by key1, key2
limit 0, 4

您的最终查询将变为:

select t.*
from your_table t
where exists (
    select 1
    from tb_dts t2
    where (key1, key2) in (
        select key1, key2
        from the_keys_table
        order by key1, key2
        limit 0, 4
    ) and t1.id = t.fieldname
);

答案 1 :(得分:0)

你的问题似乎有点令人困惑,但据我的理解,如果你想要的是在WHERE field IN clause中使用id,你可以使用子查询。所以在你的情况下,select key1,key2,group_concat(Id) from tb_dts group by key1,key2 limit 4,4;可以简单地成为

select field 
from table_name 
where id IN 
  (select group_concat(Id) 
   from tb_dts group by key1,key2 limit 4,4)

您可以找到谷歌子查询以了解更多信息。让我知道你对这种方法的看法。希望这可能是一个步骤。

答案 2 :(得分:0)

你可以试试这个

select  *
    from  tb_dts
    where  Id IN (
        SELECT  r2.Ids from
                  ( SELECT  group_concat(Id) Ids
                    from  tb_dts as r1
                    group by  r1.key1,r1.key2
                    limit  4,4
                  ) r2 
                 );

答案 3 :(得分:0)

第1步:放弃你想象的分页方案。而是在key上分页,而不是“每页4行”。

第2步:“记住你离开的地方”。如果第一页具有key1 = 1或2的所有对,则第二页以key1 = 2之后的下一个值开始。

现在查询变得更有效率,因为它超过key1值的“范围”。目前,它必须在分页之前构建整个输出!

More在不使用OFFSET的情况下讨论分页。