|
|
|
Формирование отчета об изменении данных без повторов (извещения о событиях)
|
|||
|---|---|---|---|
|
#18+
Здравствуйте! Я опишу сначала упрощенный вариант задачи, а ниже объясню откуда она появилась и какое решение мне удалось получить. Предположим, есть такая таблица с данными: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Подскажите, пожалуйста, как можно написать запрос, чтобы получить такой результат: Код: plaintext 1. 2. 3. 4. 5. 6. 7. В результате должен получится отсортированный по X вывод, в котором есть только такие строки, в которых содержится отличное от ПРЕДЫДУЩЕЙ значение Y. Хотя набор исходных данных не упорядочен по определению, проще понять, что требуется, смотрять на вывод "select * from T" и сравнивая значения "предыдущей" и "текущей" строк: X Y --------- 1 1 <-- эта строка должна быть в результате - у нее просто нет "предыдущей" 2 1 <-- не должна, не изменился Y 3 1 <-- не должна, не изменился Y 4 2 <-- должна, изменился Y 5 3 <-- должна, изменился Y 6 3 <-- не должна, не изменился Y 7 3 <-- не должна, не изменился Y 8 4 <-- должна, изменился Y 9 5 <-- должна, изменился Y К моему сожалению, пока мои знания SQL ограничены 2-хдневным чтением Стандарта SQL-92, а потому получающиеся конструкции выглядят крайне неуклюже, хотя как-то иногда и работают. Я пока не "чувствую", какой из подходов сработает в той или иной ситуации, поэтому хотелось бы увидеть решение, которое использовали бы профессионалы. На мой взгляд, просто удалить дубликаты нельзя, поскольку Y может иметь произвольное значение, а удалять дубли надо только для соседних строк. Например, если "select * from T" выдает: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. то в результате выполнения требуемого запроса должно получится: Код: plaintext 1. 2. 3. 4. 5. 6. 7. Попытки так и эдак применить удаление дублей не увенчались успехом. Возможно, я просто не умею их готовить... У меня же в итоге получился вот такой ужос: Код: plaintext 1. 2. 3. 4. 5. 6. 7. Решение использует тот факт, что все значения x - различны. Только тогда имеет смысл сравние для выбора наибольшего из всех меньших. Проверял я работу операторов в SQLite, как наболее простой и понятном мне инструменте с SQL, который смог найти с ходу. Возможно, из-за этого у меня возникла проблема: почему-то select max(x) всегда возвращает результат, даже если таблица пустая! Правда, в этом случае результат NULL, но его не отличить с помощью оператора exists. Пришлось сделать трюк с проверкой в еще одном select x = select max(x), где сравнение с NULL просто отбрасывается. Задача возникла из необходимости сократить количество событий, которые требуют внимания оператора. Разнообразные данные ("состояния") генерируются несколькими источниками, но внимание требуется только тогда, когда "что-то случилось" - изменилось "состояние". Использование триггеров и пр. невозможно, есть уже готовый набор данных (протокол работы). Есть только отчет, где указаны "состояния" в хронологическом порядке, примерно вот так. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. А хотелось бы иметь: Код: plaintext 1. 2. 3. 4. 5. 6. Объем отслеживаемых событий сокращается драматически. Как же это можно сделать элегантным способом? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.10.2008, 19:51 |
|
||
|
Формирование отчета об изменении данных без повторов (извещения о событиях)
|
|||
|---|---|---|---|
|
#18+
sleepyhead Хотя набор исходных данных не упорядочен по определению, проще понять, что требуется, смотрять на вывод "select * from T" и сравнивая значения "предыдущей" и "текущей" строк:В SQL несуществует понятий "предыдущая" и "следующая" строка. Если они есть в задаче - пытайся придумать как переформулировать задачу без них. sleepyheadВозможно, из-за этого у меня возникла проблема: почему-то select max(x) всегда возвращает результат, даже если таблица пустая!Это не проблема, так и должно быть. Запрос с агрегатной функцией всегда выдает одну строку на группу. Если агрегат не может посчитаться (нет значений например) он возвращает null. sleepyheadЗадача возникла из необходимости сократить количество событий, которые требуют внимания оператора. Разнообразные данные ("состояния") генерируются несколькими источниками, но внимание требуется только тогда, когда "что-то случилось" - изменилось "состояние". Использование триггеров и пр. невозможно, есть уже готовый набор данных (протокол работы). Есть только отчет, где указаны "состояния" в хронологическом порядке, примерно вот так. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. А хотелось бы иметь: Код: plaintext 1. 2. 3. 4. 5. 6. Объем отслеживаемых событий сокращается драматически. Как же это можно сделать элегантным способом?Такие задачи обычно решаются либо через хранимые процедуры, курсоры и временные таблицы. Либо через OLAP функции, но sqlite их делать не умеет пока. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.10.2008, 17:49 |
|
||
|
Формирование отчета об изменении данных без повторов (извещения о событиях)
|
|||
|---|---|---|---|
|
#18+
White Owlsleepyhead Хотя набор исходных данных не упорядочен по определению, проще понять, что требуется, смотрять на вывод "select * from T" и сравнивая значения "предыдущей" и "текущей" строк:В SQL несуществует понятий "предыдущая" и "следующая" строка. Перед отправкой своего вопроса просмотрел форум и, зная, что часто вопрошающих тычут носом в факт "таблицы - это наборы данных, никак не упорядоченные", написал так, чтобы было понятно, что я тоже это уже понимаю . Особо подчеркнул, что "набор исходных данных не упорядочен по определению". И даже написал, что рассматриваю не исходный набор, а вывод - только, чтобы проще объяснить условие задачи. Согласитесь, что вывод может быть упорядоченным? Наверное, мне стоило написать "select * from T order by X ". White OwlЕсли они есть в задаче - пытайся придумать как переформулировать задачу без них. У меня есть отношение порядка, заданное для данных одного из столбцов (здесь - для Х). Т.е. действительно есть "предыдущий" и "следующий". И только используя эти понятия, я могу сформулировать задачу. Как их не называй, суть от этого не изменится. Вероятно, я просто не понимаю, что значит переформулировать задачу? Не могли бы Вы показать на каком-либо примере, хотя бы на этом, как это можно сделать? White OwlЕсли агрегат не может посчитаться (нет значений например) он возвращает null. Спасибо, это я пропустил при изучении SQL! White OwlТакие задачи обычно решаются либо через хранимые процедуры, курсоры и временные таблицы. Либо через OLAP функции, но sqlite их делать не умеет пока. Спасибо, буду знать. Но в указанной задаче я не зря написал, что подобных возможностей нет, требуется извлечь отчет по указанной форме из уже готовой таблицы. Конкретно для этого случая есть какие-либо идеи? Какие есть проблемы с предложенным решением? Можно ли что-то улучшить в нем или же надо применить какой-то совершенно другой подход? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.10.2008, 20:08 |
|
||
|
Формирование отчета об изменении данных без повторов (извещения о событиях)
|
|||
|---|---|---|---|
|
#18+
sleepyheadWhite OwlЕсли они есть в задаче - пытайся придумать как переформулировать задачу без них.У меня есть отношение порядка, заданное для данных одного из столбцов (здесь - для Х). Т.е. действительно есть "предыдущий" и "следующий". И только используя эти понятия, я могу сформулировать задачу. Как их не называй, суть от этого не изменится. Вероятно, я просто не понимаю, что значит переформулировать задачу? Не могли бы Вы показать на каком-либо примере, хотя бы на этом, как это можно сделать?Эту фразу я писал прочитав только первый пример, с пятью различными Y. Второй пример и пример реальных данных уже действительно сложно описать по другому... sleepyheadКонкретно для этого случая есть какие-либо идеи? Какие есть проблемы с предложенным решением? Можно ли что-то улучшить в нем или же надо применить какой-то совершенно другой подход?Проблем с предложенным решением я с ходу не вижу. Вроде-бы работает... Хотя я бы его переписал вот так: Код: plaintext 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.10.2008, 20:57 |
|
||
|
Формирование отчета об изменении данных без повторов (извещения о событиях)
|
|||
|---|---|---|---|
|
#18+
White Owl, спасибо! Сейчас буду соображать, как работает Ваш запрос... Действительно, это пока я сам запрос написал, понимаю, какое поле к чему относится, а вот разобраться, скажем, через неделю, будет сложновато... Совет мне кажется весьма дельным, впредь буду делать именно так! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.10.2008, 08:33 |
|
||
|
|

start [/forum/topic.php?fid=56&msg=35616874&tid=2015866]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
155ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
54ms |
get tp. blocked users: |
2ms |
| others: | 19ms |
| total: | 275ms |

| 0 / 0 |

Извините, этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
... ля, ля, ля ...