Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задачка по SQL, нужна помощь в решении 
V
    Опции темы
Kangaroo
Дата 4.2.2008, 00:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

Репутация: нет
Всего: 104



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

не могу решить задачу по SQL, столкнулся с несколькими проблемами..

Условие.
Цитата

Таблица, хранящая квадраты - utQ (Q_ID int,Q_NAME varchar(35)) 
Предполагая, что среди идентификаторов квадратов имеются пропуски, найти минимальный и максимальный "свободный" идентификатор в диапазоне между имеющимися максимальным и минимальным идентификаторами.
Если пропусков нет, выводить NULL.
Например, для последовательности идентификаторов квадратов 1,2,5,7 результат должен быть 3 и 6


Теперь, собственно, вопросы:
1) Не могу понять как в SQL можно выбрать любое число. То есть запрос типа SELECT Любое_число FROM utQ WHERE условия... 
2) Как сделать - "Если пропусков нет, выводить NULL" ? Может есть ли какие-нибудь операторы условия в SQL?

Надеюсь понятно объяснил.
Спасибо заранее  smile 




--------------------
Lost....
PM MAIL MSN   Вверх
XEugene
Дата 4.2.2008, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 1.1.2008

Репутация: нет
Всего: 2



Что-то такое
Код

select min(Q_ID), max(Q_ID) 
from utQ 
where Q_ID between (select min(Q_ID) from utQ) and (select max(Q_ID) from utQ)
and Q_ID not in(select Q_ID from utQ)
  
а вывод null в случае отсутствия пропусков можно попробовать сделать через left join таблицы самой с собой.

Это сообщение отредактировал(а) XEugene - 4.2.2008, 12:18
PM MAIL   Вверх
Kangaroo
Дата 4.2.2008, 00:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

Репутация: нет
Всего: 104



Цитата(XEugene @  3.2.2008,  23:39 Найти цитируемый пост)
Что-то такое

Я вот тоже так пытался сделать, но это не то...  Потому что в селекте стоит min(Q_ID), а нужно выбрать идентификатор, которого нету в таблице. Вот я и хотел узнать как выбрать любое_число, а не поле из какой-нибудь таблицы.


--------------------
Lost....
PM MAIL MSN   Вверх
Deniz
Дата 4.2.2008, 06:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 6
Всего: 44



Выбирает все дырки в диапазоне:
Код

select t1.id + 1 as id
from table t1
  left join table t2 on ((t1.id + 1) = (t2.id))
where (t1.id between 1 and 10)
  and (t2.id is null)
order by t1.id

немного изменив запрос можно выбрать 1 мин и 1 мах.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
XEugene
Дата 4.2.2008, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 116
Регистрация: 1.1.2008

Репутация: нет
Всего: 2



Цитата(Kangaroo @  4.2.2008,  00:45 Найти цитируемый пост)
Потому что в селекте стоит min(Q_ID), а нужно выбрать идентификатор, которого нету в таблице.
Ага,  поторопился.

Добавлено через 3 минуты и 28 секунд
В sql есть возможность генерировать рандомные числа.  В MSSQL функция rand().
PM MAIL   Вверх
Kangaroo
Дата 4.2.2008, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

Репутация: нет
Всего: 104



Deniz, 
спасибо за наводку. Пока вот такое страшное получилось:
Код

SELECT min(num) as q_min, max(num) as q_max FROM (
SELECT min(t1.Q_ID + 1) as num
FROM utQ t1
WHERE 
((t1.Q_ID+1) BETWEEN (SELECT min(Q_ID) FROM utQ) AND (SELECT max(Q_ID) FROM utQ)) 
AND
((t1.Q_ID+1) NOT IN (SELECT Q_ID FROM utQ))
UNION
SELECT max(t1.Q_ID-1) as num
FROM utQ t1
WHERE 
((t1.Q_ID-1) BETWEEN (SELECT min(Q_ID) FROM utQ) AND (SELECT max(Q_ID) FROM utQ)) 
AND
((t1.Q_ID-1) NOT IN (SELECT Q_ID FROM utQ))
)


Добавлено через 2 минуты и 27 секунд
У меня это на Оракле работает, а у них на сервере (не знаю какая БД) выдает 
Цитата

Incorrect syntax near ')'.

 smile 


Цитата(XEugene @  4.2.2008,  10:20 Найти цитируемый пост)
В sql есть возможность генерировать рандомные числа.  В MSSQL функция rand(). 

Я не думаю, что в задачах по SQL (и это тока 12я задача  smile  ) используется какие-то необычные функции.. 



--------------------
Lost....
PM MAIL MSN   Вверх
Kangaroo
Дата 4.2.2008, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

Репутация: нет
Всего: 104



Все, прошел дальше  smile 

Deniz получает плюса в репу, спасибо.
XEugene тоже спасибо за участие.

Если кто знает как сделать этот же запрос красивее - отписываемся, буду рад улучшениям  smile 


--------------------
Lost....
PM MAIL MSN   Вверх
Deniz
Дата 4.2.2008, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 6
Всего: 44



Kangaroo, ну ты и запрос написал, с этими скобками не разберешься.
Можно и вот так написать:
Код

SELECT min(num) as q_min, max(num) as q_max FROM 
(
  SELECT min(t1.Q_ID + 1) as num
    FROM utQ t1
    WHERE 
    ((t1.Q_ID+1) < (SELECT max(Q_ID) FROM utQ))
-- не обязательно проверять min(Q_ID) когда у нас t1.Q_ID+1 оно всегда больше min
-- проверку на <= тоже ставить не обязательно
      AND
    ((t1.Q_ID+1) NOT IN (SELECT Q_ID FROM utQ))
  UNION
  SELECT max(t1.Q_ID-1) as num
    FROM utQ t1
    WHERE 
      ((t1.Q_ID-1) > (SELECT min(Q_ID) FROM utQ)) -- тоже самое как у min только про max
      AND
      ((t1.Q_ID-1) NOT IN (SELECT Q_ID FROM utQ))
)

можно все min и max во вложенных запросах поменять на select top 1 ... order by Q_ID asc/desc


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
APM
Дата 5.2.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 13.7.2007

Репутация: нет
Всего: 6



А откуда Вы такие задачки по SQL берете? Может поделитесь?
PM   Вверх
Kangaroo
Дата 5.2.2008, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

Репутация: нет
Всего: 104



Цитата(Deniz @  4.2.2008,  14:51 Найти цитируемый пост)
Kangaroo, ну ты и запрос написал, с этими скобками не разберешься.
Можно и вот так написать:

Пока как умею, так и писал  smile За замечания спасибо.


Цитата(APM @  5.2.2008,  10:42 Найти цитируемый пост)
А откуда Вы такие задачки по SQL берете? Может поделитесь? 

Тут


--------------------
Lost....
PM MAIL MSN   Вверх
elephunk
Дата 10.3.2008, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 10.3.2008

Репутация: нет
Всего: нет



Цитата(Deniz @ 4.2.2008,  15:51)
Kangaroo, ну ты и запрос написал, с этими скобками не разберешься.
Можно и вот так написать:
Код

SELECT min(num) as q_min, max(num) as q_max FROM 
(
  SELECT min(t1.Q_ID + 1) as num
    FROM utQ t1
    WHERE 
    ((t1.Q_ID+1) < (SELECT max(Q_ID) FROM utQ))
-- не обязательно проверять min(Q_ID) когда у нас t1.Q_ID+1 оно всегда больше min
-- проверку на <= тоже ставить не обязательно
      AND
    ((t1.Q_ID+1) NOT IN (SELECT Q_ID FROM utQ))
  UNION
  SELECT max(t1.Q_ID-1) as num
    FROM utQ t1
    WHERE 
      ((t1.Q_ID-1) > (SELECT min(Q_ID) FROM utQ)) -- тоже самое как у min только про max
      AND
      ((t1.Q_ID-1) NOT IN (SELECT Q_ID FROM utQ))
)

можно все min и max во вложенных запросах поменять на select top 1 ... order by Q_ID asc/desc

Ребята, в чем ошибка понять не могу!!!

Добавлено через 1 минуту и 35 секунд
Цитата(Deniz @ 4.2.2008,  15:51)
Kangaroo, ну ты и запрос написал, с этими скобками не разберешься.
Можно и вот так написать:
Код

SELECT min(num) as q_min, max(num) as q_max FROM 
(
  SELECT min(t1.Q_ID + 1) as num
    FROM utQ t1
    WHERE 
    ((t1.Q_ID+1) < (SELECT max(Q_ID) FROM utQ))
-- не обязательно проверять min(Q_ID) когда у нас t1.Q_ID+1 оно всегда больше min
-- проверку на <= тоже ставить не обязательно
      AND
    ((t1.Q_ID+1) NOT IN (SELECT Q_ID FROM utQ))
  UNION
  SELECT max(t1.Q_ID-1) as num
    FROM utQ t1
    WHERE 
      ((t1.Q_ID-1) > (SELECT min(Q_ID) FROM utQ)) -- тоже самое как у min только про max
      AND
      ((t1.Q_ID-1) NOT IN (SELECT Q_ID FROM utQ))
)

можно все min и max во вложенных запросах поменять на select top 1 ... order by Q_ID asc/desc

Ребята, в чем ошибка понять не могу!!!
чо ему скобка не угодила
PM MAIL   Вверх
Deniz
Дата 11.3.2008, 07:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 6
Всего: 44



А поставь в самом конце какую-нибудь латинскую букву


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
mediate
Дата 2.4.2008, 03:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.4.2008

Репутация: нет
Всего: нет



Код

SELECT min(num) as q_min, max(num) as q_max FROM 
(
  SELECT min(Q_ID + 1) as num
    FROM utQ
    WHERE 
    (
not (q_id+1) = any(select q_id from utq)
    )
  UNION
  SELECT max(Q_ID-1) as num
    FROM utQ
    WHERE 
     (
not (q_id-1) = any(select q_id from utq)
      )
)д

упростил немного... только я не думал, что так будет просто...я заморочился до разрывов в порядке не в 1, а в 2 и более, т.е. в последовательности, например, 1,4,5,7,12 найти среди пропущеных мин и макс... 
никто не знает - как это реализовать? тут уже не обойдешся +- 1 Давайте подумаем? smile
PM MAIL   Вверх
Deniz
Дата 2.4.2008, 08:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

Репутация: 6
Всего: 44



А что думать, в данном диапазоне min=2 max=11, и запрос это должен выдавать нормально.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
mediate
Дата 2.4.2008, 09:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.4.2008

Репутация: нет
Всего: нет



Deniz, ок. Скажем так -  как получить список всех пропусков?
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0623 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.