Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: SQL: работа со смежными строками  (Прочитано 25785 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Kern
Гость
« : 08-12-2003 13:37 » 

Допустим есть таблица
Код:
CREATE TABLE tab )id int, date_time timestamp without time zone, string varchar)30:,PRIMARY KEY)id::;
и заполнена она примерно таким образом:
    1, '2003.08.12 12:00', 'timber'
    2, '2003.08.12 12:00', 'timber'
    4, '2003.08.12 13:00', 'kern'
    6, '2003.08.12 13:01', 'hack'
    7, '2003.08.12 13:05', 'timber'
    8, '2003.08.12 13:07', 'timber'
    10, '2003.08.12 13:07', 'timber'
    12, '2003.08.12 13:08', 'hack'[/list:u] Так вот, надо удалить "повторяющиеся записи", оставив первое вхождение в данном случае это строчки с id=(2,8,10) SQL - запросом.
    Допустимо использовать несколько одинаковых SQL вподряд. Упрощение - строка не может повторяться более 5 раз.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 08-12-2003 17:44 » 

Попробуй так:
Код:
SELECT t1.id
 FROM table AS t1
 LEFT JOIN table AS t2 ON t2.id=)t1.id+1:
 WHERE t1.date_time=t2.date_time AND t1.string=t2.string;

Удалять на основании полученных данных (id повторных строк). Если СУБД поддерживает вложенные запросы, то:
Код:
DELETE FROM table
 WHERE id IN )SELECT ...:;

Недостаток: СУБД должна поддерживать работу с одной и той же таблицей с разными псевдонимами.
Данный пример может быть некоректным, но ход мыслей верный. Этот код не проверял, но такой же код у меня работал на MySQL - искал пропуски в id.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Alf
Гость
« Ответ #2 : 08-12-2003 21:25 » 

Цитата: RXL
Попробуй так:
Код:
SELECT t1.id
 FROM table AS t1
 LEFT JOIN table AS t2 ON t2.id=)t1.id+1:
 WHERE t1.date_time=t2.date_time AND t1.string=t2.string;

...

Поленился проверить на реальном сервере, но показалось, что в данном решении имеется пара неувязочек.
Первая - совсем мелкая. По условию нужно удалять все дубликаты, кроме первого вхождения. А тут как раз первое вхождение и становится жертвой удаления. Но это ерунда, заменить id+1 на id-1 - и вроде должно заработать.
А вот вторая посерьезнее будет. В приведенном выше запросе мы закладываемся на то, что нумерация записей - последовательная. Но из примера видно, что это не так. Например, записи с id=(8,10) под условие
Код:
t2.id=)t1.id+1:
явно не попадают и обнаружены не будет.
По моему опыту, красивое непроцедурное решение подобных задач в общем случае удается найти нечасто, только если на данные наложены строгие ограничения, как в данном случае - последовательная нумерация id.
На мой взгляд, единственный выход - в процедурном решении: заводить курсор, сканировать записи по одной и выбрасывать дубликаты. Некрасиво, конечно, но зато работает.
Записан
Kern
Гость
« Ответ #3 : 09-12-2003 05:59 » 

тогда как вариант - можно создать временную табличку и скопировать туда оригинальную
Код:
CREATE TEMP TABLE temp_table )id AUTOINCREMENT, tab_id int, string varchar)30:, PRIMARY KEY )id::;
INSERT INTO temp_table VALUES)tab_id,string: SELECT id,string FROM tab ORDER BY date_time;
здесь AUTOINCREMENT - какое-либо средство БД обеспечить автоматическое инкрементирование.
И уже к этой табличке применять SELECT с LEFT JOIN и т.п... а на основе его удалать из оригинальной.... а потом и временную табличку грохнуть...

мда... при таких изврашениях и при очень большой таблице - IMHO это слишком накладно....
Записан
little
Помогающий

de
Offline Offline
Пол: Мужской

« Ответ #4 : 09-12-2003 07:33 » 

А насколько критичны имеющиеся ID ?
Если они не нужны, сделать Select Distinct или Distinctrow (не помню чем они отличаются), а в результате проставить новые ID
Записан
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #5 : 09-12-2003 07:41 » 

Для проверки записей для удаления

Код:
SELECT tmpid FROM
           )SELECT MIN)id: as tmpid, date_time, string
            FROM tab
            GROUP BY date_time, string: AS tmp:


если то что надо, тогда

Код:
DELETE FROM tab
WHERE id NOT IN )SELECT tmpid FROM
)SELECT MIN)id: as tmpid, date_time, string
FROM tab
GROUP BY date_time, string: AS tmp::


проверял, работало
ЗЫЖ на всякий случай сделай копию
Записан

I Have Nine Lives You Have One Only
THINK!
Kern
Гость
« Ответ #6 : 09-12-2003 08:44 » 

HandKot, Проверил код, не удаляется запись с ID=8. Если запрос на удаление повторить - то все равно более ничего не удаляется.
Записан
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #7 : 09-12-2003 09:54 » 

Kern,
А почему она должна удалить запись с id=8
Запрос удалил запись с id=10 -> осталась запись №8
повторяющихся записей больше нет

объясни получше, не могу понять
Записан

I Have Nine Lives You Have One Only
THINK!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 09-12-2003 11:17 » 

Цитата: HandKot
Kern,
А почему она должна удалить запись с id=8
Запрос удалил запись с id=10 -> осталась запись №8
повторяющихся записей больше нет

объясни получше, не могу понять
Потому что, она дублирует строку с id=7.

little, так нельзя. Нужно удалить строки не повторяющиеся во всей базе, а лишь следующие друг за другом в порядке id.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #9 : 09-12-2003 12:39 » 

Цитата: Kern

7, '2003.08.12 13:05', 'timber'
8, '2003.08.12 13:07', 'timber'


RXL,
 время разное - > записи не дублируются

или нужен отсев по часам?
Записан

I Have Nine Lives You Have One Only
THINK!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 09-12-2003 12:48 » 

HandKot, извиняй - округлил малость  Ага
Кстати, действительно - пробел в задании: что есть "повторяющиеся записи"? Если у них может быть разное время, то какая разница допустима (для смежных и крайних в последовательной группе)?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kern
Гость
« Ответ #11 : 10-12-2003 05:52 » 

HandKot, RXL, "повторяющиеся записи" это записи, имеющие одинаковое поле string и идущие друг за другом после
Код:
SELECT * FROM tab ORDER BY date_time;
То есть табличка tab - это нечто вроде журнала событий и нужно убрать все подряд идущие одинаковые события, оставив только первое из них. Улыбаюсь
Записан
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #12 : 10-12-2003 06:45 » 

Kern,
тогда в этом случае
SQL для выборки

Код:
SELECT T1.id  
FROM tab AS T1
WHERE T1.string LIKE )SELECT TOP 1 T2.string
FROM tab AS T2
WHERE T1.id > T2.id
ORDER BY T2.date_time DESC:



и SQL для удаления

Код:
DELETE FROM tab
WHERE id IN
                  )SELECT T1.id  
                   FROM tab AS T1
                   WHERE T1.string LIKE )SELECT TOP 1 T2.string
  FROM tab AS T2
  WHERE T1.id > T2.id
  ORDER BY T2.date_time DESC::


ЗЫ вместо оператора LIKE можно поставить =
и не забудь сделать копию таблицы, на всякий случай  Улыбаюсь [/b]
Записан

I Have Nine Lives You Have One Only
THINK!
Kern
Гость
« Ответ #13 : 10-12-2003 15:17 » 

HandKot, SELECT дает не те записи - точнее дает только одного timber и выдает ID-шники всех timber'ов идущех после первого (2,7,8,10) но 7-ой то не должен удаляться - он же не вподряд после timber идет - он уже после hack идет. если в табличку добавить еще парочку записей, например
    14, '2003.08.12 13:09', 'hack'
    9, '2003.08.12 14:04', 'hack'[/list:u] (Если присмотреться - то можно заметить что ID-шники идут не по порядку Улыбаюсь ) то они все равно не выделяются данным SELECTом. (если сделать ID по порядку - то же самое)
    Ключевое слово TOP - моя БД не поняла Жаль (Postgress 7.2 может там что-то по другому написать нада) так что SELECT пришлось заменить на
Код:
SELECT T1.id,T1.date_time,T1.string
FROM tab AS T1
WHERE T1.string LIKE
    )SELECT string FROM tab
     WHERE id=)SELECT min)T2.id:
                      FROM tab AS T2 WHERE T1.id > T2.id::
ORDER BY date_time;
Записан
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #14 : 11-12-2003 08:17 » 

Kern,
твой запрос у меня вообще отработал не правильно

входные данные:
1   2003-08-12 12:00:00.000   timber
2   2003-08-12 12:00:00.000   timber
4   2003-08-12 13:00:00.000   kern
6   2003-08-12 13:01:00.000   hack
7   2003-08-12 13:05:00.000   timber
8   2003-08-12 13:07:00.000   timber
10   2003-08-12 13:07:00.000   timber
12   2003-08-12 13:08:00.000   hack
14   2003-08-12 13:09:00.000   hack
9   2003-08-12 14:04:00.000   hack

выходые данные:
2   2003-08-12 12:00:00.000   timber
7   2003-08-12 13:05:00.000   timber
8   2003-08-12 13:07:00.000   timber
10   2003-08-12 13:07:00.000   timber

странно
может разница в реализации SQL?
Записан

I Have Nine Lives You Have One Only
THINK!
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #15 : 11-12-2003 08:24 » 

Kern,
вот еще один запросик от меня, проверь
Код:

SELECT id, string, dtmdate
FROM )SELECT min)id: as id, date_time, string from tab
group by date_time, string: as t
WHERE string not like )SELECT TOP 1 tmp.string
FROM tab AS tmp
WHERE t.date_time > tmp.date_time
ORDER BY tmp.date_time desc:
or
not exists )SELECT TOP 1 tmp.string
FROM tab AS tmp
WHERE t.date_time > tmp.date_time
ORDER BY tmp.date_time desc:

order by t.date_time



вот результаты:
входные данные:
1   2003-08-12 12:00:00.000   timber
2   2003-08-12 12:00:00.000   timber
4   2003-08-12 13:00:00.000   kern
6   2003-08-12 13:01:00.000   hack
7   2003-08-12 13:05:00.000   timber
8   2003-08-12 13:07:00.000   timber
10   2003-08-12 13:07:00.000   timber
12   2003-08-12 13:08:00.000   hack
14   2003-08-12 13:09:00.000   hack
9   2003-08-12 14:04:00.000   hack
выходные данные:
1   timber   2003-08-12 12:00:00.000
4   kern   2003-08-12 13:00:00.000
6   hack   2003-08-12 13:01:00.000
7   timber   2003-08-12 13:05:00.000
12   hack   2003-08-12 13:08:00.000

Запрос немного корявый (самому не нравиться Жаль ), но вроде работает

и по поводу команды "TOP" - стандартная SQL команда, для выборки только первой записи из набора записей (может в твоем случае есть похожие типа FIRST, ..., и т.д.)

ЗЫЖ Проверь и сообщи.
Записан

I Have Nine Lives You Have One Only
THINK!
Kern
Гость
« Ответ #16 : 11-12-2003 13:32 » 

HandKot, Ёу! запрос что нада Улыбаюсь в моем случае вместо TOP нада использовать LIMIT:
Код:
SELECT id, string, date_time
FROM )SELECT min)id: as id, date_time, string from tab
group by date_time, string: as t
WHERE string not like )SELECT tmp.string
      FROM tab AS tmp
      WHERE t.date_time > tmp.date_time
      ORDER BY tmp.date_time desc LIMIT 1:
or
not exists )SELECT tmp.string
   FROM tab AS tmp
   WHERE t.date_time > tmp.date_time
   ORDER BY tmp.date_time desc LIMIT 1:

order by t.date_time
Входные-выходные данные точно такие же, при усложнении данных (типа добавление таблички tab самой к себе со смещенным временем и id) тоже пахает как нада! Улыбаюсь

Сколько нада с SQL-ом работать чтобы дорасти до таких "приятностей"? Улыбаюсь
Записан
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #17 : 11-12-2003 13:46 » 

1,5 часа и напарник Отлично
Записан

I Have Nine Lives You Have One Only
THINK!
Raf^Dimas
Гость
« Ответ #18 : 04-03-2004 18:35 » 

Ja ne ponimaju 4to eti vse 4isla zna4at From Select Where  bred kakojto po etapno bi objasnili kak i 4to pisatj i gde   Ха-ха-ха   Ха-ха-ха   Ха-ха-ха
Записан
Raf^Dimas
Гость
« Ответ #19 : 04-03-2004 18:38 » 

Objasnite plzzzzz kak namana mo#no vvesti vse kodi 4to oni rabotali i dlja 4ego oni  voob6e zna4at
Записан
Raf^Dimas
Гость
« Ответ #20 : 04-03-2004 18:41 » 

Ili mo#et kto sajt znaet kakoj nibudj 4tob tam  Hack Cheat ili 4to libo drugoe bilo na  MU
Записан
Anonymous
Гость
« Ответ #21 : 04-03-2004 18:45 » 

Kern, Objasni popodrobnee kak i 6to delatj
Записан
Kern
Гость
« Ответ #22 : 05-03-2004 04:42 » 

Raf^Dimas, Я не врубился чего ты не понял Улыбаюсь
Что такое MU?
про какие коды ты говоришь? про id?

короче, чего тебе надо?

(если можешь пиши лучше на нормальном русском)
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines