Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

SQL - запрос на удаление по условию [MSSQL]


Страницы:   1 2

Ольга ©   (2005-07-06 16:46:00) 

Что-то меня сегодня клинит, не могу правильно написать простой запрос на удаление. Прошу помощи.
Есть таблица T1: (ID int,  
                 Р  int,  
                 S  int,
                 VAL float)
Сочетание ID,P,S - уникальное.
Нужно в таблице оставить записи, где значение S максимальное для каждого сочетания ID,P, но не больше заданного значения (допустим 4).

Вот мой неработающий вариант (не ругается, но и не удаляет ненужное из таблицы):
DELETE  FROM T1 WHERE NOT EXISTS  
        (SELECT d.ID,d.P,d.S,d.VAL
         FROM  T1 d,
              (select ID,P,max(S) as S
               from T1
               where  S<=4
               group by ID,P) d1                
         WHERE  d.ID=d1.ID AND d.P=d1.P AND d.S=d1.S)


ЮЮ   (2005-07-07 05:01:00) [1]

Запрос:
       SELECT d.ID,d.P,d.S,d.VAL
       FROM  T1 d,
            (select ID,P,max(S) as S
             from T1
             where  S<=4
             group by ID,P) d1                
       WHERE  d.ID=d1.ID AND d.P=d1.P AND d.S=d1.S
выдает то, что надо оставить в таблице.
Как бы прикрутить к этому DELETE?


Так прямо и прикрутить.
Соединив то, что надо оставить с тем что есть, получим для удаляемых записей NULL вместо полей:

DELETE T
FROM
(
  SELECT ID, P, max(S) S
  FROM T
  WHERE  S<=4
  это условие лишнее, т.к. если есть запись с S = 4, 5 и 6
  то c S = 4 останется, а с большими - удалятся !!!

  GROUP BY ID, P
) Rest
LEFT JOIN T ON  (T.Id = Rest.Id) AND (T.P = Rest.P) AND (T.S = Rest.S)
WHERE
 Rest.Id IS NULL Ольга ЮЮ ©
Ваш скрипт работает неправильно. Rest.Id никогда не будет IS NULL. Может я невнятно изложила, что мне надо. Давайте на примере. В таблице есть данные:

ID    P    S    Val

10    1    0    5.2
10    1    1    5.3
10    1    2    5.31
10    2    0    8
10    2    5    7.8
11    1    0    12
11    1    3    12.6
11    2    0    18

После удаления должны остаться "жирные" записи. ЮЮ © Почему
10    2     0   8
а не
10    2     5   7.8 ?

>Rest.Id никогда не будет IS NULL

Sorry, там надо RIGHT JOIN
сначала я написал
 T LEFT JOIN () Rest,
но потом подумал, что тогда не будет работать индекс по ID,P,S
и поменял местами, не исправмл LEFT на RIGHT Virgo_Style © ЮЮ ©   (07.07.05 8:28) [23]
Почему


Наверное, потому что

> где значение S максимальное для каждого сочетания
> ID,P, но не больше заданного значения
Ольга
> Почему
> 10    2    0    8
> а не
> 10    2    5    7.8 ?

А это как раз должно сработать дополнительное условие: S<=4

Выполняю скрипт:
DELETE T1
FROM
( SELECT ID, P, max(S) S
 FROM T1
 WHERE  S<=4
 GROUP BY ID, P
) Rest
RIGHT OUTER JOIN T1 ON  (T1.Id = Rest.Id) AND (T1.P = Rest.P) AND (T1.S = Rest.S)
WHERE T1.Id IS NULL

Результат:
(0 row(s) affected) ЮЮ © а select *
from <ДАЛЕЕ ПО ТЕКСТУ> ? ЮЮ © А КАК ЖЕ
Ольга   (06.07.05 17:41) [10]
Поле S - это порядковый номер корректировки поля VAL для ID и P.
Нужно в таблице оставить только последнююкорректировку (для каких-то сочетаний ID и P это будет 1, для других 5 ). ЮЮ © DELETE T1
FROM
( SELECT ID, P, max(S) S
FROM T1
WHERE  S<=4
GROUP BY ID, P
) Rest
RIGHT OUTER JOIN T1 ON  (T1.Id = Rest.Id) AND (T1.P = Rest.P) AND (T1.S = Rest.S)
WHERE T1.Id IS NULL

В предложенном (и удаляющем) вырианте было

Rest.Id IS NULL ЮЮ © А спасибо где? Что я зря таблицу создавал и данные вколачмвал, чтобы убедиться, что на практике мои теоретические познания подтаерждаются? :) Ольга Я здесь отвлеклась на производственные проблемы...
Да, конечно, Rest.Id IS NULL. Это я пока меняла лево на право... в общем сено-солома получилось, sorry.
Все заработало!
СПАСИБО!
БОЛЬШОЕ СПАСИБО!
ОГРОМНОЕ СПАСИБО! (и "КУ" с приседанием 3 раза). evvcom ©
> и "КУ" с приседанием 3 раза

А желтые штаны дарствовать?


Ольга   (2005-07-06 18:04:00) [2]


> да и домой пора

Пожалуй. Утро вечера мудренее.
Спасибо.


Johnmen   (2005-07-06 18:02:00) [3]

PS
Я бы сам проверил, да только сервер MSSQL в перманентном дауне, да и домой пора...:)


Johnmen   (2005-07-06 18:00:00) [4]

>> СКОЛЬКО РАЗ будет выполнен вложенный запрос
>Один. Сначала выполнится внутренний запрос, а потом внешний:

Если ты в этом уверена, то см.[5]


Ольга   (2005-07-06 17:58:00) [5]


> СКОЛЬКО РАЗ будет выполнен вложенный запрос

Один. Сначала выполнится внутренний запрос, а потом внешний:
DELETE FROM Table T1
WHERE T1.S< 4 AND T1.S<=4


Johnmen   (2005-07-06 17:57:00) [6]

Т.е. условие WHERE ему как бы побарабану ?


Ольга   (2005-07-06 17:56:00) [7]


> что возвращает этот запрос в отношении таблицы

4 - максимальное значение S из всех сочетаний ID,P


Johnmen   (2005-07-06 17:54:00) [8]

А кто спорит ? Никто.
Всё дело СКОЛЬКО РАЗ будет выполнен вложенный запрос.


Ольга   (2005-07-06 17:53:00) [9]

Что-то я не врубаюсь.
Агрегатные функции в конструкциях типа
SELECT AgrFun(X) FROM ...
всегда выдают 1 значение - это SQL стандарт


Johnmen   (2005-07-06 17:49:00) [10]

т.к.
SELECT MAX(T2.S)
FROM Table T2
WHERE T2.ID=T1.ID AND T2.P=T1.P
выдает 1 запись, естественно.


Естественно, что одну.
Другой вопрос, на каждую ли запись таблицы ?
Если нет, то это проблемы парсера, про него я уже упоминал.
Кстати, просто интересно, если это действительно так, то что возвращает этот запрос в отношении таблицы?


Ольга   (2005-07-06 17:46:00) [11]

Запрос:
        SELECT d.ID,d.P,d.S,d.VAL
        FROM  T1 d,
             (select ID,P,max(S) as S
              from T1
              where  S<=4
              group by ID,P) d1                
        WHERE  d.ID=d1.ID AND d.P=d1.P AND d.S=d1.S
выдает то, что надо оставить в таблице.
Как бы прикрутить к этому DELETE?


Ольга   (2005-07-06 17:41:00) [12]

Поле S - это порядковый номер корректировки поля VAL для ID и P.
Нужно в таблице оставить только последнюю корректировку (для каких-то сочетаний ID и P это будет 1, для других 5).
Так вот, удаляются только те, для которых S>4, т.к.
SELECT MAX(T2.S)
 FROM Table T2
 WHERE T2.ID=T1.ID AND T2.P=T1.P
выдает 1 запись, естественно.


Johnmen   (2005-07-06 17:39:00) [13]

>Seg   (06.07.05 17:34) [8]
>Наверное забыли
>group by ID,P

Не забыли. Оно (она?) здесь ни к чему.


Seg   (2005-07-06 17:34:00) [14]

Наверное забыли
group by ID,P


Johnmen   (2005-07-06 17:33:00) [15]

>но данные удаляются неправильно - только те, где S>4

Ну да, что не так ?
М.б. более чётко сфjрмулировать
>Нужно в таблице оставить записи, где значение S максимальное
>для каждого сочетания ID,P, но не больше заданного значения
>(допустим 4).
а то можно и по-другому сынтерпретировать...:)


Ольга   (2005-07-06 17:28:00) [16]

Явно указала таблицу - теперь претензий к синтаксису у сервера нет, но данные удаляются неправильно - только те, где S>4 (т.к. это max S из всех сочетаний ID,P)


Johnmen   (2005-07-06 17:17:00) [17]

1. Ну да. Указывать явно. Но тут может быть засада. Всё зависит от принципов работы парсера, а они мне для MSSQL неизвестны.
Для парсера IB будет засада, для MySQL - нет.
2. Так выберет же для текущего сочетания ID,P.


Ольга   (2005-07-06 17:12:00) [18]

Нет, так не получится.
1. Нельзя использовать псевдоним в конструкции DELETE FROM Table Т1
2. SELECT MAX(T2.S) выберет 1 значение, а мне нужно для каждого сочетания ID,P


Johnmen   (2005-07-06 17:01:00) [19]

конечно же T1.S>4


Johnmen   (2005-07-06 17:00:00) [20]

DELETE FROM Table T1
WHERE (T1.S<
 (SELECT MAX(T2.S)
  FROM Table T2
  WHERE T2.ID=T1.ID AND T2.P=T1.P)) AND T1.S<=4


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо