|
|
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Есть задача: 1. Дана таблица T (какая СУБД не имеет значения). 2. В таблице есть 1 столбец с названием ID. 3. В таблице располагается натуральная, возрастающая последовательность с "пропусками". Использую СУБД MySQL 5.0. Нужно: Написать один select - запрос, который бы вывел все числа из каждого "пропуска" последовательности. Например: Последовательность: 1,2,3,7,8,9,11,20,.... Решение: 4,5,6,10,12,13,14,15,16,17,18,19,... Каждое число последовательности это запись в столбике T.ID. То есть SELECT - запрос должен вывести те числа, которые нужно вставить в последовательность, чтобы получить ряд натуральных чисел. Как это сделать? Интересно с помощью чего это можно сделать если даже забыть про один select - запрос. P. S. Я так понял один select - запрос - это отсутствие соотнесённых под запросов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.02.2011, 23:16:20 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhY, получить в виде резалт сета из N строк, где N - количество пропусков одним SELECTом для любого количества пропусков не получится. Получить в виде резалт сета из одной строки и одной колонки с разделенными некоторым символом(ами) пропусками - получится. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.02.2011, 23:33:54 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhY(какая СУБД не имеет значения)Имхо, либо нужно иметь физическую опорную таблицу (содержащую все возможные значения ID), либо решение будет СУБД-зависимым. Т.е. вам нужно определиться, что для вас более приемлемо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 09:26:56 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
miksoftИмхо, либо нужно иметь физическую опорную таблицу (содержащую все возможные значения ID), либо решение будет СУБД-зависимым. Т.е. вам нужно определиться, что для вас более приемлемо. Я надеюсь, что (какая СУБД не имеет значения) - это не призыв к использованию стандарта SQL, а предоставление выбора СУБД мне, хотя может быть это и не так. А вот добавлять ещё одну таблицу со всеми возможными значениями ID - нельзя. Если б можно было добавить табл. AllPossible в столбику ID которого хранились бы все возможные значения ряда: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20 ..., то задача решалась бы так: SELECT AllPossible.ID FROM T RIGHT JOIN AllPossible ON T.ID=AllPossible.ID WHERE T.ID IS NULL; Это дало бы требуемый результат: 4,5,6,10,12,13,14,15,16,17,18,19,... НО нет у нас опорной таблицы. Поэтому подскажите пожалуйста СУБД зависимое решение. Хоть для какой нибудь СУБД, можно для MySQL. Поэтому изменю шапку задачи: 1. Дана таблица T (можно использовать любую СУБД). 2. В таблице есть 1 столбец с названием ID. 3. В таблице располагается натуральная, возрастающая последовательность с "пропусками". an0nymПолучить в виде резалт сета из N строк, где N - количество пропусков одним SELECTом для любого количества пропусков не получится. Получить в виде резалт сета из одной строки и одной колонки с разделенными некоторым символом(ами) пропусками - получится.. Спасибо за такой уточненный ответ. Потому что я не знаю как это можно сделать, а Вы знаете что этого сделать нельзя. Отсутствие решения тоже решение, а может быть лучшее из них. Вбивать в одну строку через пробелы (разделители) последовательность я думаю нельзя, но если бы можно было подскажите каким образом выдрать пропущенные (недостающие) элементы натурального ряда . P.S. Спасибо что не оставляли комментариев про тупость использования БД для хранения такого рода информации, потому что это ОЧЕВИДНО тупо, но может пригодится. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 13:04:51 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhYmiksoftИмхо, либо нужно иметь физическую опорную таблицу (содержащую все возможные значения ID), либо решение будет СУБД-зависимым. Т.е. вам нужно определиться, что для вас более приемлемо. Я надеюсь, что (какая СУБД не имеет значения) - это не призыв к использованию стандарта SQL, а предоставление выбора СУБД мне, хотя может быть это и не так.Ну это уже вам решать. ArhYА вот добавлять ещё одну таблицу со всеми возможными значениями ID - нельзя. Если б можно было добавить табл. AllPossible в столбику ID которого хранились бы все возможные значения ряда: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20 ..., то задача решалась бы так: SELECT AllPossible.ID FROM T RIGHT JOIN AllPossible ON T.ID=AllPossible.ID WHERE T.ID IS NULL; Это дало бы требуемый результат: 4,5,6,10,12,13,14,15,16,17,18,19,... НО нет у нас опорной таблицы. Поэтому подскажите пожалуйста СУБД зависимое решение. Хоть для какой нибудь СУБД, можно для MySQL. Поэтому изменю шапку задачи: 1. Дана таблица T (можно использовать любую СУБД). 2. В таблице есть 1 столбец с названием ID. 3. В таблице располагается натуральная, возрастающая последовательность с "пропусками". Все способы, которые мне приходят в голову, собственно, сводятся к уже предложенному вами запросу. Только опорная таблица берется не реально существующая, а генерится "виртуальная". Вот этот способ генерации "вирутальной" таблицы и различается в разных СУБД. Можно сделать так: 1) Взять любую таблицу, где гарантированно достаточно записей. Если готовой нет, то взять любую и помножить ее саму на себя два или более раз. 2) пронумеровать записи в "виртуальной" таблице из пункта 1. В случае с MySQL нумерация делается переменными, см. FAQ: Нумерация строк и другие вопросы про использование переменных . 3) подставить конструкцию из пункта 2 в ваш вариант запроса вместо AllPossible. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 13:44:49 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhYСпасибо за такой уточненный ответ. Потому что я не знаю как это можно сделать, а Вы знаете что этого сделать нельзя. Отсутствие решения тоже решение, а может быть лучшее из них. Вбивать в одну строку через пробелы (разделители) последовательность я думаю нельзя, но если бы можно было подскажите каким образом выдрать пропущенные (недостающие) элементы натурального ряда . Вы немного не поняли. На входе будет таблица из множества строк, содержащих идентификаторы, с пропусками, а на выходе резалт сет из одной строки одной колонки, содержащий перечисление пропусков через запятую (или другой разделитель). Если такой способ подойдет, то я знаю специфичное решение на диалекте MySQL. Остальные способы реализуются как объяснил miksoft и ограничения накладываются именно в части возможности генерации нужного набора строк без изменения структуры запроса. В MySQL это сделать нельзя. В Oracle можно. В MS SQL можно. В Postgres не знаю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 13:53:26 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 13:53:57 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
qwerty112, на большой таблице в MySQL запрос повесится. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 15:23:55 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
an0nymqwerty112, на большой таблице в MySQL запрос повесится.Да и, строго говоря, там запрос не для этой задачи. А если приводить к этой, то опять придем к опорной таблице. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 15:32:25 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
an0nymОстальные способы реализуются как объяснил miksoft и ограничения накладываются именно в части возможности генерации нужного набора строк без изменения структуры запроса. В MySQL это сделать нельзя. В Oracle можно. В MS SQL можно. В Postgres не знаю .Там есть generate_series, т.е. тоже можно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 15:44:55 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
miksoftan0nymqwerty112, на большой таблице в MySQL запрос повесится.Да и, строго говоря, там запрос не для этой задачи. А если приводить к этой, то опять придем к опорной таблице . ну в общем - так и есть, разве что можно обойтись без таблицы, а "крутить" что-то типа этого Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 19:33:20 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
qwerty112, а теперь сделайте тоже самое для значений <=999; <=9999 и т. д. Об этом всю тему и рассказывают. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 20:10:21 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
an0nymqwerty112, а теперь сделайте тоже самое для значений <=999; <=9999 и т. д. Об этом всю тему и рассказывают. вот сразу видно, что Вы практик ))) а ТС, даже не заморачивается указанием/выбором конкретной СУБД, не то что "скорострельностью" - an0nymна большой таблице в MySQL запрос повесится но и, тем более, эстетической красотой )) интиресует простой/банальный вопрос - "можно ли это сделать одним селектом" ? ArhY Нужно: Написать один select - запрос, который бы вывел все числа из каждого "пропуска" последовательности. я правда не знаю, что он имел ввиду под "соотнесённых под запросов" ArhYP. S. Я так понял один select - запрос - это отсутствие соотнесённых под запросов. соотнесённых - это кореллированных ?? но если дерив.тейбл - под это ограничение НЕ попадают, то я бы ответил, что При определённом ограничении а) макс.номер ИД - НЕ более чем столькото (чуть проще) или б) макс. величина "дырки" между ИД - НЕ более чем столькото (чуть сложнее) - это вполне возможно и плевать на сложность/время выполнения - главное, что такая возможность есть ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 22:36:16 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
miksoftМожно сделать так: 1) Взять любую таблицу, где гарантированно достаточно записей. Если готовой нет, то взять любую и помножить ее саму на себя два или более раз. 2) пронумеровать записи в "виртуальной" таблице из пункта 1. В случае с MySQL нумерация делается переменными, см. FAQ: Нумерация строк и другие вопросы про использование переменных . 3) подставить конструкцию из пункта 2 в ваш вариант запроса вместо AllPossible. Сделал так (работает, хоть и не всегда): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. А теперь для тех, кто первый раз читает эту тему (по пунктам от miksoft ): 1) Поскольку кроме табл. Т других таблиц нет, то будем использовать именно её. На хранящееся в ней (в базе) данные это не повлияет. Помножить таблицу (множество, англ. set) значит найти "декартово произведение" этой таблицы (множества) с другой табл. (множеством). Я помножил табл. T саму на себя так: Код: plaintext Код: plaintext Псевдоним Self нужен из-за одинаковых имён таблиц (имена одинаковые поскольку мы умножаем T на T). Поэтому нельзя быть уверенным , что TхT будет содержать достаточно записей. Например: Если выходная таблица состоит из двух записей: 1, 100, то результатом запроса должна быть последовательность: 2, 3, 4, 5, 6, ..., 95, 96, 97, 98, 99. Но TxT будет содержать всего 4 записи. Не хватает. Если TxT содержит чересчур много записей, то убираем лишние вот так: Код: plaintext 1. 2. 3. 2) Пронумеруем записи в виртуальной таблице TxT (см. ссылку в посте miksoft ): Код: plaintext 1. 3) Подставляем, это всё в мой вариант и получим запрос, который приведён в начале этого поста. P. S. Это работает для примера, который приведён вначале темы. В каждом конкретном случае, нужно смотреть во сколько раз помножить табл. Т: ТхТ, ТхТхТ, ТхТхТхТ и т. д. Имхо, задача не стандартна и решение тоже. Это работает. Спасибо miksoft . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 22:59:14 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhY, я бы не стал трогать базовую таблицу - дешевле системную. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 23:27:15 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
qwerty112я правда не знаю, что он имел ввиду под "соотнесённых под запросов"ArhYP. S. Я так понял один select - запрос - это отсутствие соотнесённых под запросов. Имел ввиду такого вида: СООТНЕСЕННЫЕ ПОДЗАПРОСЫ . Как видите из предыдущего моего поста - я забил на один select - запрос и какая СУБД не имеет значения . Использовал подзапросы и переменные в MySQL. Потому что an0nym написал, что первоначальное задание вообще не реально выполнить.an0nymполучить в виде резалт сета из N строк, где N - количество пропусков одним SELECTом для любого количества пропусков не получится. an0nym подскажите пожалуйста каким образом и с помощью каких особенностей диалекта MySQL. an0nymArhYСпасибо за такой уточненный ответ. Потому что я не знаю как это можно сделать, а Вы знаете что этого сделать нельзя. Отсутствие решения тоже решение, а может быть лучшее из них. Вбивать в одну строку через пробелы (разделители) последовательность я думаю нельзя, но если бы можно было подскажите каким образом выдрать пропущенные (недостающие) элементы натурального ряда. Вы немного не поняли. На входе будет таблица из множества строк, содержащих идентификаторы, с пропусками, а на выходе резалт сет из одной строки одной колонки, содержащий перечисление пропусков через запятую (или другой разделитель). Если такой способ подойдет, то я знаю специфичное решение на диалекте MySQL. P. S. Вы правы qwerty112 . Если бы не такая тупость и одновременно сложность в постановке задачи, то еще можно было бы говорить о производительности. Но ... Теперь я сам же пропускаю ограничения на один select - запрос и какая СУБД не имеет значения и это не предел, но надеюсь уже достаточно. qwerty112и плевать на сложность/время выполнения - главное, что такая возможность есть ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 23:36:28 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhYqwerty112я правда не знаю, что он имел ввиду под "соотнесённых под запросов"пропущено... Имел ввиду такого вида: СООТНЕСЕННЫЕ ПОДЗАПРОСЫ . Я бы вам советовал использовать термин коррелированный подзапрос (correlated subquery, dependent subquery). Соотнесенный подзапрос я встречаю впервые, несмотря на то, что это статья на SQL.ru. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2011, 23:44:22 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
On 21.02.2011 23:16, ArhY wrote: > Написать *один* select - запрос, который бы вывел все числа из каждого > "пропуска" последовательности. > *Например:* > Последовательность: 1,2,3,7,8,9,11,20,.... > Решение: 4,5,6,10,12,13,14,15,16,17,18,19,... > > Каждое число последовательности это запись в столбике T.ID. > > То есть SELECT - запрос должен вывести те числа, которые нужно вставить в > последовательность, чтобы получить ряд натуральных чисел. Как это сделать? Это НУЖНО делать с помощью обычного цикла. Делать это с помощью SQL нецелесообразно. К тому же SQL не может генерировать новые данные из ниоткуда, вам придётся как минимум создать таблицу всех номеров 1,2,3,4,5,....(бесконечность) Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2011, 00:00:13 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhY, Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Уверен, запрос можно оптимизировать. :) Впрочем, этот запрос достаточно извращен в любом случае. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2011, 00:16:55 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
[quot ArhY] 1. Дана таблица T (какая СУБД не имеет значения). 2. В таблице есть 1 столбец с названием ID. 3. В таблице располагается натуральная, возрастающая последовательность с "пропусками". для оракла, например, так: Код: plaintext 1. где generator_natural - твоя юзерская табличная функция, которая возвращает натуральную последовательность, ограниченную параметром, хотя в оракле можно и без функции достать последовательность нужную: Код: plaintext вот проверенное решение (для оракла :): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2011, 10:28:08 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
Наверно наиболее быстрый способ: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2011, 11:59:41 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
an0nymя бы не стал трогать базовую таблицу - дешевле системную. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Да. Так работает. У меня сервер MySQL под *nix системой, поэтому заменил маленькую t на большую T. Для примера который есть в самом первом посте M >= 5, N <= (SELECT MAX(T.id) FROM T) или просто <= 20. Следующее решение лучше тем, что не используется декартово произведение, а просто пробегаем от 0 до MAX(T.ID) и смотрим с помощью EXIST есть ли @rownum в исходной таблице. Не понял зачем там USE, CREATE, DROP. Вроде и без них работать должно. an0nym Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Вопрос. Вроде понимаю, как это должно работать, но когда проверяю аналогичный запрос на работоспособность, то выбивает предупреждение и всё. BENCHMARK(20, Бла-бла) работает нормально, а вот BENCHMARK(t.id, Бла-Бла) - не работает, хотя Код: plaintext Спасибо an0nym классный вариант для MySQL. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.02.2011, 01:32:43 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
SQL Bigot , для Oracle, впрочем как и для других серверов БД, интересны решения, которые не используют мои юзерские функции, а вот этот вариант действительно интересен. SQL Bigotвот проверенное решение (для оракла :): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Попробую скачать Oracle и разобраться. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.02.2011, 01:52:47 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
ArhY, покажите конечный запрос и ошибку, которую он выдает. Насчет 5.0 сейчас лень вспоминать, возможно там что-нибудь из того, что я использую не поддерживается. Если вы обучаетесь MySQL, с 5.0 начинать не советую - как минимум 5.1, а лучше 5.5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.02.2011, 01:57:02 |
|
||
|
Волшебство с помощью чистого SELECTA-а.
|
|||
|---|---|---|---|
|
#18+
an0nymпокажите конечный запрос и ошибку, которую он выдает. Насчет 5.0 сейчас лень вспоминать, возможно там что-нибудь из того, что я использую не поддерживается. Если вы обучаетесь MySQL, с 5.0 начинать не советую - как минимум 5.1, а лучше 5.5. Мой запрос это результат выбрасывания под-запросов с приведённого Вами запроса, в попытках выяснить что не так. Вот приведённый Вами запрос: Код: plaintext 1. 2. 3. 4. 5. 6. Результат выполнения на MySQL 5.0 : MySQL said:#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'T.id, (SELECT LEAST(0, @rownum := @rownum + 1, CASE WHEN NOT EXISTS( SE' at line 3 Результат выполнения на MySQL 5.5 : 1 row in set (0.00 sec)+---------------------------------------------+ 4, 5, 6, 10, 12, 13, 14, 15, 16, 17, 18, 19 +---------------------------------------------+ Что является правильным результатом. Повторюсь: всё из-за того, что в MySQL 5.0 BENCHMARK не хочет в качестве количества повторений принимать t.id, а только конкретное число (скаляр). Но указание конкретного числа, это явно хуже чем использование Код: plaintext ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.02.2011, 23:27:41 |
|
||
|
|

start [/forum/topic.php?fid=47&msg=37131450&tid=1832456]: |
0ms |
get settings: |
7ms |
get forum list: |
15ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
29ms |
get topic data: |
7ms |
get forum data: |
1ms |
get page messages: |
45ms |
get tp. blocked users: |
1ms |
| others: | 193ms |
| total: | 302ms |

| 0 / 0 |
