|
|
|
Правильная группировка по пересечениям
|
|||
|---|---|---|---|
|
#18+
В упрощённом виде задача выглядит так Имеются 2 таблицы вида: 1) Главная (main_table) id_t (int) | parent (varchar) | price (int) Пример данных: 1 | '' | 198 2 | '' | 50 3 | '' | 167 2) С дополняющими данными (part_table) id_p (int) | id_t (int) | part (varchar) Пример данных: 1 | 1 | 'гвоздь' 2 | 1 | 'доска' 3 | 1 | 'гайка' 4 | 1 | 'шуруп' 5 | 1 | 'болт' 6 | 2 | 'саморез' 7 | 2 | 'дсп' 8 | 2 | 'лампа' 9 | 2 | 'балка' 10 | 3 | 'шуруп' 11 | 3 | 'гайка' 12 | 3 | 'дсп' 13 | 3 | 'двп' 14 | 3 | 'лампа' Алгоритм следующий: Из первой таблицы выбираются поочерёдно строки с сортировкой от минимального price к максимальному. Далее выбираются строки стоящие выше по price и смотрится пересечение по 2-ой таблице до первого минимального совпадения (например по 2 пунктам). Если нашли совпадение, то нижестоящий прикрепляется к вышестояещему, а дальше пересечение ищется уже для вышестоящего. В данном случае будет сперва выбрана строка id_t=2 (у неё наименьший price).Вторым этапом выбирается строка с большим price, это будет id_t=3. Смотрим пересечения по part_table, в данном случае пересечения "дсп" и "лампа", мы прикрепляем дочерний к вышестоящему и дальше смотрим пересечения для вышестоящего. 1 | '' | 198 2 | '2' | 50 3 | 'main' | 167 Выбираем вышестоящий по price - это будет id_t=1, смотрим пересечения по part_table и находим "шуруп" и "гайка", поэтому мы их объединяем, теперь главный - id_t=1. 1 | 'main' | 198 2 | '1' | 50 3 | '1' | 167 Ищем для id_t=1 вышестоящих, но их уже нет, поэтому ставим статус группы - обработано. 1 | 'main_done' | 198 2 | '1' | 50 3 | '1' | 167 Постарался разжевать свои мысли, код тоже прикрепляю, но проблема в том, что при наличии 9к ключей в главной таблице и ~90к в дочерней, всё это жуётся очень долго (жевало пару суток). Каким образом лучше перестроить данные и запросы, чтобы это работало гораздо шустрее? Запросы: авторSELECT * FROM main_table WHERE id_t!=".$top['id_t']." and price>=".$top['price']." ORDER BY price, id_t desc SELECT count(*) FROM part_table as table1, part_table as table2 WHERE table1.id_t=".$top['id_t']." and table2.id_t=".$pod_top['id_t']." and table2.part=table1.part php код: авторfunction union_parent($top) { global $msconnect; //выборка в цикле оставшихся строк, выше по price $pod_top3 = mysql_query("SELECT * FROM main_table WHERE (status='".$main_id."' OR id_t=".$main_id.") and id_t!=".$top['id_t']." and `parent`!='".$top['id_t']."' and price>=".$top['price']." ORDER BY price, id_t desc", $msconnect); while($pod_top=mysql_fetch_array($pod_top3)) { //выбираем совпадения $pod_data=mysql_query("SELECT count(*) FROM part_table as table1, part_table as table2 WHERE table1.id_t=".$top['id_t']." and table2.id_t=".$pod_top['id_t']." and table2.part=table1.part", $msconnect); $pod_dat=mysql_fetch_array($pod_data); //если есть совпадения if($pod_dat[0]>2) { if($pod_top['parent']=='main_done'){ //если совпадение с вышестоящим, но который был обработан и глава группы mysql_query("update main_table set `parent`='".$pod_top['id_t']."' WHERE id_t=".$top['id_t']." or `parent`='".$top['id_t']."'", $msconnect); }elseif($pod_top['parent']==''){ //если совпадение с вышестоящим, который не был обработан mysql_query("update main_table set `parent`='".$pod_top['id_t']."' WHERE id_t=".$top['id_t']." or `parent`='".$top['id_t']."'", $msconnect); mysql_query("update main_table set `parent`='main' WHERE id_t=".$pod_top['id_t'], $msconnect); return union_parent($pod_top); }else{ //если совпадение с вышестоящим, который был обработан и он в группе, но не её глава mysql_query("update main_table set `parent`='".$pod_top['parent']."' WHERE id_t=".$top['id_t']." or `parent`='".$top['id_t']."'", $msconnect); } return true; } } //если никого не нашли, то ставим его в гордом одиночестве mysql_query("update main_table set `parent`='main_done' WHERE id_t=".$top['id_t'], $msconnect); } //выбираем в цикле строки $do=true; while($do){ $top3 = mysql_query("SELECT * FROM main_table WHERE `parent`='' or `parent`='main' ORDER BY price, id_t desc limit 0,1", $msconnect); if(mysql_num_rows($top3)>0){ $top=mysql_fetch_array($top3); union_parent($top); }else $do=false; } ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2013, 13:51:30 |
|
||
|
Правильная группировка по пересечениям
|
|||
|---|---|---|---|
|
#18+
Вот честно - раз пять перечитал и ничего не понял... :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2013, 15:19:58 |
|
||
|
Правильная группировка по пересечениям
|
|||
|---|---|---|---|
|
#18+
Добрый Э - ЭхВот честно - раз пять перечитал и ничего не понял... :( Значит я плохо донёс мысль, какие вопросы возникли при чтении? Я постараюсь всё разжевать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2013, 16:15:00 |
|
||
|
Правильная группировка по пересечениям
|
|||
|---|---|---|---|
|
#18+
ZubeQкакие вопросы возникли при чтении? Вопрос один - читал ли ты Как правильно задавать вопросы - Описывайте цель, а не отдельный шаг ... а если читал - почему не следуешь совету? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2013, 16:26:21 |
|
||
|
Правильная группировка по пересечениям
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2013, 22:57:22 |
|
||
|
Правильная группировка по пересечениям
|
|||
|---|---|---|---|
|
#18+
ZubeQ, SELECT * FROM main_table WHERE id_t!= Сослепу не заметил сразу. Эта часть за микроскопическим исключением эквипенисуальна запросу вида SELECT * FROM main_table Доведем эксперимент до чистоты. $id = 0 Таких id не бывает, следовательно вы получите ВСЮ таблицу взад как будто никакого условия не было в помине. $id = 1; Всю таблицу за исключением 1 записи. Если запрос еще и умножает таблицы - то немудрено двое суток жевать теорию несуществования. ЗЫ По моим наблюдением в этой рубрике 90 процентов оффтопика который в тему в рубрике проектирование БД, или как она там, где рамочки рисуют. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.07.2013, 23:25:16 |
|
||
|
|

start [/forum/topic.php?fid=47&msg=38320838&tid=1836495]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
45ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
38ms |
get tp. blocked users: |
1ms |
| others: | 209ms |
| total: | 332ms |

| 0 / 0 |
