2017-01-30 4 views
0

я получил таблицу, как показано нижеКак получить Идентификаторы из 4 различных значений (сочетание 2-х ключей)

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 Я получаю Идентификаторы как хорошо, но я хочу использовать этот Идентификаторы в WHERE Field IN статье как where somefield IN (..here my Ids goes...)

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 содержит более что 30 миллионов reocrds и 15 полей в реальном, я не могу использовать ID BETWEEN min_id and max_id

Для обработки первых 4 уникальных значений комбинационного мне нужно

select * from tb_dts where Id IN (1,2,3,8,9,10,11,12,4,5,6,7,17,18,19 ) 

для обработки следующих 4 уникальных комбинированных значений мне нужны Идентификаторы в моем приложении, поэтому в общем я хочу иметь нижеуказанные идентификаторы в моей статье where Field IN

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

Вот структура моего стола

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) 

Но я ожидаю все Ids, которое подпадает под заданные критерии, это ничего, кроме того, что все идентификаторы падают ниже 4 уникальных значений

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.

1 
2 
3 
8 
9 
10 
11 
12 
4 
5 
6 
7 
17 
18 
19 
+0

Вопрос запутан. Просто сделайте то, что ваш 'input' и что ваш ожидаемый' output'. – Sadikhasan

+0

см. Обновление выше – user3637224

+0

вы используете предел правильно, но вы должны сделать заказ по Id. Поэтому Id никогда не повторится –

ответ

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 
); 

Хотя я не уверен, что это лучший способ сделать то, что вы» сделав. Создание строк с использованием группы, а затем поиск в этой строке будет слишком медленным.

Кроме того, вы хотите иметь индекс для столбцов 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 
); 
+0

'^ 1' wow, это потрясающе, спасибо за ваш ценный ответ, кажется, работает, я дам вам знать, если проблема любая из них – user3637224

+0

@ user3637224 Любая причина для непризнания? – GurV

+0

, но я до сих пор не ожидал o/p для данного ввода – user3637224

0

вам вопрос кажется немного запутанным, но из моего понять, что вы хотите использовать идентификаторы в WHERE field IN clause вы можете использовать подзапросы. Так что в вашем случае, когда вы были 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) 

Вы можете найти Google подзапросов, чтобы узнать больше. Дайте мне знать, что вы думаете об этом подходе. Надеюсь, это может быть шагом.

+0

Свыше одной MySQL не поддерживает «LIMIT & IN/ALL/ANY/SOME subquery», поэтому вам нужно исправить, как 'where ID in (select * (выберите group_concat (Id) из группы tb_dts по key1, key2 limit 4,4) как q) ', извините, что это не работает' group_concat' не может помочь здесь, вот почему я ожидал, что o/p Ids в строка не как строка – user3637224

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 
       ); 
+0

Это не сработает: 'Каждая производная таблица должна иметь свой собственный псевдоним',' group_concat' внутри 'where IN' clause не будет работать так – user3637224

+0

@ user3637224 вы можете попробовать сейчас –

+0

Жаль, что это не работает – user3637224

0

Шаг 1: Отказаться от схемы постраничной вы себе представляете. Вместо этого разбивайте страницы на key, а не на «4 строки на страницу».

Шаг 2: «Помните, где вы остановились». Если на первой странице есть все пары для ключа1 = 1 или 2, вторая страница начинается со следующего значения после ключа1 = 2.

Теперь запрос становится намного более эффективным, так как он находится над «диапазоном» key1 значения. В настоящее время он должен построить весь вывод, прежде чем он сможет разбиваться на страницы!

More обсуждение разбиения на страницы без использования OFFSET.