@lolrofl01

Можно ли построить такой запрос на sql?

Привет!
Имеем такую проблему. Есть таблица в БД, в таблице есть записи. Все как обычно, 1 запись - 1 айди. Когда создаешь новую запись, она добавляется в бд, у нее есть специальное поле parent. И при добавлении новой записи поле равно 0. При изменении этой записи на самом деле создается новая, но поле parent теперь равно не нулю, а айди записи, которая была создана в первый раз. Тут суть в том, что в админке отображаются все версии определенной статьи. Какая статья была в самом начале, и как она потом менялась. Отсюда столько записей. Но теперь встала необходимость вывести на сайте эти записи, разумеется, последние их версии. Вот как построить такой запрос, чтобы грубо говоря, выводились все записи у которых parent = 0 (все новые записи), при условии, что у этих статей нет детей (измененных записей, у которых parent = айди этой статьи).
Можно ли такое вообще сделать через запрос?
  • Вопрос задан
  • 385 просмотров
Пригласить эксперта
Ответы на вопрос 3
@masterfreelance
программист со стажем
id | parent_id

1 | 0
2 | 0
3 | 1 (вот она - первая редакция первой записи)
4 | 2 (первая редакция второй записи)
5 | 0
6 | 1 (вторая редакция первой записи)
7 | 2 (вторая редакция второй записи)

Определите сначала для себя алгоритм
1.Выбрать все записи с parent_id = 0 (это у вас все статьи)
2.Выбрать записи с parent_id = id(из выбрки записей п.1) и максимальным id записи (получите все последние редакции статей)
3.Выбрать записи с parent_id = 0 и id нет в поле parent_id из выборки записей п.2 (статьи не имеющие редакций)
4.Объединить наборы записей п.2 и п.3

Вам осталось только описать этот алгоритм языком SQL
Ответ написан
usdglander
@usdglander
Yipee-ki-yay
Можно.
Выбирайте все строки со всеми "дочками" с помощью OUTER JOIN, используйте группировку по id и count, а потом WHERE [count] = 1.

upd: Извиняюсь, не WHERE, а HAVING, конечно же.
Ответ написан
@ViaCom
Увы я не пишу на мускуле, потому пример для MS SQL
но полагаю с минимальными правками он будет работать и на мускуле.
drop table if exists t1;
create table t1
(Id int primary key, Parent_Id int, code nvarchar(10), TextValue nvarchar(max));
-- Если у стаьи с разной версионностью есть набор полей (или одно поле, у меня это CODE)
-- Которые гарантированно уникальны, тогда все много проще

insert into t1(Id, Parent_Id, code, TextValue) values (1,0, 'Message', 'The variant');
insert into t1(Id, Parent_Id, code, TextValue) values (2,1, 'Message', 'The variant.');
insert into t1(Id, Parent_Id, code, TextValue) values (3,2, 'Message', 'Variant.');
insert into t1(Id, Parent_Id, code, TextValue) values (4,0, 'Letter', 'Hi dear Kat');
insert into t1(Id, Parent_Id, code, TextValue) values (5,4, 'Letter', 'Hi Kat');

-- запрос обычный вложенный
select * from t1 a 
join (select code, max(Parent_Id) Parent_Id from t1 group by code )b 
on a.code = b.code and a.Parent_Id = b.Parent_Id;
-- но если появляется такой "колобок" как описано ниже
-- у нас колобок с Id 6 и колобок с Id 8 это последнии 
-- ревизии разных статей с одним кодом.
insert into t1(Id, Parent_Id, code, TextValue) values (6,0, 'Kolobok', 'K1');
insert into t1(Id, Parent_Id, code, TextValue) values (7,0, 'Kolobok', 'K2');
insert into t1(Id, Parent_Id, code, TextValue) values (8,7, 'Kolobok', 'K3');
-- тогда запрос выйдаст не красивый результат
select * from t1 a 
join (select code, max(Parent_Id) Parent_Id from t1 group by code )b 
on a.code = b.code and a.Parent_Id = b.Parent_Id;

-- нужно делать иерархический запрос, например такой.
with z (Kod, id, parent_id, code, TextValue) as 
(
	select Kod=a.id, a.id, a.parent_id, a.code, a.TextValue from t1 a where parent_id = 0
	union all 
	select z.Kod, a.id, a.parent_id, a.code, a.TextValue from t1 a
	join z on a.Parent_Id = z.id
)
select z.* from z join (select Kod, id = max(id) from z group by Kod ) x on z.Id = x.id;
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы