SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 02.07.2007 23:36:19

gregzem
Участник
Зарегистрирован: 02.07.2007
Сообщений: 10

Сортировка строк внутри группы

Здравствуйте,

Делаем раз:

SELECT ID, Priority, RealID FROM MyTable WHERE ParentID='0' ORDER BY Priority;
 

Код:

+----------+----------------+--------------+
| ID       | Priority       | RealID       |
+----------+----------------+--------------+
|        1 |              1 |            1 |
|        9 |              1 |            1 |
|        2 |              2 |            2 |
|       11 |              2 |            3 |
|        3 |              3 |            3 |
|       10 |              3 |            2 |
+----------+----------------+--------------+

Делаем два:

SELECT MAX(ID) as ID, RealID FROM  MyTable WHERE ParentID='0' GROUP BY RealID ORDER BY Priority;

 

Код:

+----------+--------------+
| ID       | RealID       |
+----------+--------------+
|        9 |            1 |
|       10 |            2 |
|       11 |            3 |
+----------+--------------+

а должно быть

 

Код:

+----------+--------------+
| ID       | RealID       |
+----------+--------------+
|        9 |            1 |
|       11 |            3 |
|       10 |            2 |
+----------+--------------+

ведь сортировка идет по Priority.

Вопрос 1: как сделать выборку строк во втором запросе, чтобы строки внутри группы были отсортированы по убыванию ID).
Вопрос 2: почему второй запрос не выдает ожидаемых результатов и как будет правильный запрос?

Спасибо.

Неактивен

 

#2 03.07.2007 11:45:06

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Сортировка строк внутри группы

1. SELECT * FROM (SELECT MAX(ID) AS ID,RealID FROM MyTable GROUP BY RealID) t ORDER BY RealID DESC
2. Все зависит от того, что Вы ожидаете получить. Я, честно говоря, не понимаю, какую логику Вы преследуете.
У Вас есть RealID с разными приоритетами, у них разные ID:

Код:

root@localhost test > SELECT MAX(ID),RealID,Priority FROM MyTable GROUP BY 2,3;
+---------+--------+----------+
| MAX(ID) | RealID | Priority |
+---------+--------+----------+
|       9 |      1 |        1 | 
|       2 |      2 |        2 | 
|      10 |      2 |        3 | 
|      11 |      3 |        2 | 
|       3 |      3 |        3 | 
+---------+--------+----------+
5 rows in set (0.01 sec)

Если Вы сортируете по полю, которое не имеет групповой функции и не входит
в GROUP BY, то сервер выбирает те записи, которые он считает нужными. Стандарт
SQL вообще запрещает такие запросы. Попробуйте понять для себя, какие данные
Вы хотите получить, тогда удастся правильно переписать запрос.

Неактивен

 

#3 03.07.2007 17:10:41

gregzem
Участник
Зарегистрирован: 02.07.2007
Сообщений: 10

Re: Сортировка строк внутри группы

Спасибо за ответ. Это не совсем то, что мне нужно. Я кратко объясню суть вопроса. Буду рад получить ценные замечания относительно архитектуры и подхода. Возможно я пошел в неверном направлении.

Я пишу CMS, есть таблица, хранящая страницы сайта и структуру (все в одной таблице). Страницы сайта администратор может менять. Но пока он не нажал на кнопку "Применить", изменения не должны попасть на сайт, сайт должен отображать некую последнюю рабочую версию страниц. Таким образом нужно хранить и старые и новые изменения страниц, но админу показывать всегда последние изменения с возможностью отката до предыдущих.

У меня есть таблица, в которой хранится древовидная структура

ID | Name | ParentID | RealID | Current | Priority | и еще несколько доп полей

ID - INT PRIMARY KEY записи
Name - VARCHAR, имя узла дерева
RealID - INT, это идентификатор узла дерева
ParentID - INT, это RealID родительского узла
Priority - INT, это порядковый номер нода внутри своего поддерева

ID <> RealID.

Current - INT, зафиксированный нод (активный срез). Current = 1 - показывается посетителям. Current = 0 или Current = 1 - админу.

Все было бы очень просто, если бы не один момент. Данное дерево хранит историю изменений узлов. То есть, если, скажем, вершину переименовали (изменился Name), то создается еще одна запись в таблице, которая полностью дублирует старый нод, кроме поля

ID, Name и, возможно, Current.

Вот пример:

ID | Name | ParentID | RealID | Current | Priority | ...
1     TST1        0             1             1            1 
2     TST2        0             1             0            1 
3     TST3        0             1             0            1 

Это означает, что нод с идентификатором RealID=1 был изменен два раза. Последняя версия этого нода имеет самый старший ID, при этом Current = 1 - это то, что используется для отображения дерева (к чему можно "откатить" изменения в дереве), а Current = 0 - это новые изменения. До тех пор, пока ноду не сделают Apply(). Как только сделали Apply, активным становится тот, что с ID=3, остальные стираются из таблицы, так как больше не нужны.

Админу нужно всегда отображать дерево с самыми последними изменениями. То есть если есть


ID | Name | ParentID | RealID | Current | Priority | ...
1     TST1        0             1             1             1
2     AAA         1             2             1             1
3     TST2        0             1             0             1 
4     BBB         1             2             0              1
5     TST3        0             1             0              1

то админу надо показывать

ID = 5 (RealID = 1)
      ID = 4 (RealID = 2, ParentID = 1)

Вопрос в том, как сделать выборку из этой таблице, чтобы в ней всегда был самый последний срез (только самые свежие ноды, причем часть из них может быть изменена и иметь Current=0, а часть быть неизмененных, Current=1)

То есть, скажем, надо сделать SELECT * ... WHERE ParentID='0'... Вернуться в примере выше должно

ID | Name | ParentID | RealID | Current | ...
5     TST3        0             1             0             

Вот это запрос я и не могу составить. Допустим, нод ID = 11 переместили вверх на один уровень

было

+----------+----------------+--------------+----------------+
|    ID    |    ParentID    |     RealID   |     Priority   |
+----------+----------------+--------------+----------------+
|        9 |              0 |            1 |              1 |
|        1 |              0 |            1 |              1 |
|       11 |              0 |            2 |              2 |
|        2 |              0 |            2 |              2 |
|       10 |              0 |            3 |              3 |
|        3 |              0 |            3 |              3 |
+----------+----------------+--------------+----------------+

стало

+----------+----------------+--------------+----------------+
|    ID    |    ParentID    |     RealID   |     Priority   |
+----------+----------------+--------------+----------------+
|        9 |              0 |            1 |              1 |
|        1 |              0 |            1 |              1 |
|       11 |              0 |            3 |              2 |
|        2 |              0 |            2 |              2 |
|       10 |              0 |            2 |              3 |
|        3 |              0 |            3 |              3 |
+----------+----------------+--------------+----------------+

Какой запрос даст вот такой результат ?

+----------+----------------+--------------+----------------+
|    ID    |    ParentID    |     RealID   |     Priority   |
+----------+----------------+--------------+----------------+
|        9 |              0 |            1 |              1 |
|       11 |              0 |            3 |              2 |
|       10 |              0 |            2 |              3 |
+----------+----------------+--------------+----------------+

Следует принять во внимание, что SELECT должен извлечь "*", так как полей строки намного больше.

Буду рад любым комментариям.

Спасибо.
Григорий

Отредактированно gregzem (03.07.2007 17:13:07)

Неактивен

 

#4 03.07.2007 17:31:20

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Сортировка строк внутри группы

Насколько я понял, Вам нужно выбрать те строчки, у которых максимальный ID
при условии группировки по RealID. Думаю, проще всего этот запрос написать
вложенным запросом:

Код:

SELECT * FROM MyTable WHERE ID IN (SELECT MAX(ID) FROM MyTable WHERE (условия на parent) GROUP BY RealID);

Неактивен

 

#5 03.07.2007 17:49:36

gregzem
Участник
Зарегистрирован: 02.07.2007
Сообщений: 10

Re: Сортировка строк внутри группы

Мегаспасибо. То, что нужно. Со всеми дополнениями конечный запрос выглядит примерно так:

SELECT * FROM MyTable  WHERE ID IN (SELECT MAX(ID) FROM MyTable WHERE (ParentID='0') GROUP BY RealID) ORDER BY Priority;

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson