Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » SQL запрос

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 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

Открыть новую тему     Написать ответ в эту тему

Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Dronton2
Похоже не въехали.
Сгоревшие бонусы нигде не учитываются, но их можно вытянуть запросом. Сгоревшие бонусы для функционала списания не нужны. Таблица не больше расчетная, чем в вашем варианте. Сумма списания просто раскладывается "по полочкам". При чем тут ошибки пользователей? Ошибки могут быть в реализации, которых быть не должно.
Я предложил прозрачную РЕЛЯЦИОННУЮ схему. У вас вторая таблица нарушает реляционность, храня единичную сумму зависящую от нескольких сумм из другой таблицы без связи. Из-за этого и проблемы.
Мое дело предложить. Ваше подумать. У меня нюх на "кривую" структуру БД десятилетиямИ вырабатывался.

Всего записей: 1448 | Зарегистр. 10-07-2013 | Отправлено: 16:37 30-10-2017 | Исправлено: Alexzzy, 17:07 30-10-2017
Dronton2

Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Alexzzy
Действительно, сразу не въехал, пока не посмотрел на запрос, подсветив его синтаксис.
 
Но я всё равно не понимаю, что вы имеете ввиду, когда пишите
Цитата:
Таблица не больше расчетная, чем в вашем варианте.
. Вы ведь в интернет-магазинах сталкивались с оплатой покупок бонусами, милями и т.п.? Покупатель (или менеджер) видят одно число в поле "у вас накоплено ххх бонусов". И на вопрос "сколько бонусов списать для оплаты текущей покупки?", покупатель (или менеджер) хотят указать одно число, а не разбивать списываемые бонусы на десятки записей с привязкой к соответствующим записям начислений. У вас ведь таблица списания с отношением один ко многим. Получается, что если покупатель указывает количество списываемых бонусов одним числом, то таблица списания, которая разбивает и привязывает списание к записям начислений - расчётная, записи в которой создаются автоматически.
 
Или я опять во что-то не въехал? Тогда прошу объяснить как-то по другому.
 

Всего записей: 460 | Зарегистр. 27-06-2005 | Отправлено: 17:53 30-10-2017
Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Dronton2
С интернет-магазинами общался. В практике программирования с интернет-магазинами не сталкивался, и с оплатой покупок бонусами тоже. Это не важно. Главное - уметь представить любую задачу в реляционном виде. Интернет-магазин - это просто. Написанное мною выплывает подсознательно на этапе чтения.
 

Цитата:
И на вопрос "сколько бонусов списать для оплаты текущей покупки?", покупатель (или менеджер) хотят указать одно число, а не разбивать списываемые бонусы на десятки записей с привязкой к соответствующим записям начислений.  

 
Да, одно число, которое идет на вход хранимой процедуры (желательно).
 

Цитата:
Получается, что если покупатель указывает количество списываемых бонусов одним числом, то таблица списания, которая разбивает и привязывает списание к записям начислений - расчётная, записи в которой создаются автоматически.  

Если правильно понял, то да. Но, тут именно разбиение, а не агрегированный расчет. "Расчетная таблица" это довольно условное понятие. Главное, что здесь нет агрегированных данных.
 
Кратко про процедуру списания:
1. Открываем курсор в разрезе каждого начисления с оставшейся/доступной суммой для списания, ограничив по дате и отсортировав по дате срока действия.
2. В цикле списываем "потихоньку" требуемое количество бонусов, не больше чем оставшаяся доступная сумма по начислению, вставляя данные в таблицу списания.
 
Всё! При этом все манипуляции (включая любые последующие) с данными довольно просты и универсальны.

Всего записей: 1448 | Зарегистр. 10-07-2013 | Отправлено: 20:27 30-10-2017 | Исправлено: Alexzzy, 22:14 30-10-2017
Alexzzy

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Dronton2
Бонус.
Перечитал написанное не смотря на решение поставленной задачи.
Примечания:

Цитата:
Но, зная, что ничего постоянным не бывает, хранимая процедура сделана так, что время действия бонусов можно будет изменять.

Временной "коллапс" возникает. Данные зависят от кода процедуры и времени её вызова.
 

Цитата:
обычно, с аналитическими запросами получается меньше бойлерплейт кода. Если план такого запроса будет удовлетворительным, то можно его включать в свой арсенал, т.к. подобные задачи иногда случаются.  

По моему опыту: если с запросами проблемы - то проблемы в структуре БД. Умение обходить проблемы БД - да, это плюс. Но лучше убирать проблемы на этапе проектирования.
 

Всего записей: 1448 | Зарегистр. 10-07-2013 | Отправлено: 01:07 02-11-2017
Dronton2

Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Alexzzy

Цитата:
Временной "коллапс" возникает. Данные зависят от кода процедуры и времени её вызова.

Нет, я имел ввиду не изменение времени действия начисленных ранее бонусов, а что в момент начисления бонусов, задаётся время действия этих бонусов.
Пример: есть интернет-магазин. За покупки начисляются бонусы, которые действуют без ограничения времени. Но иногда из магазина приходят вот такие письма: "Подарок на день народного единства: +300 бонусов до 10.11.2017". Т.е., время действия этих бонусов отличается от времени действия остальных бонусов. Поэтому, от времени вызова процедуры, данные, возвращаемые ею, не зависят (если данные не менялись между вызовами процедуры).
Про создание таблицы с вычисляемыми данными - спасибо, подумаю. Пока меня останавливают лишь постоянно меняющиеся исторические данные, от которых должны зависеть данные в этой таблице, и постоянно меняющаяся постановка задачи, в некоторых вариантах которой, все вычисленные данные должны быть пересчитаны, а код, обеспечивающий их актуальность - во многих местах переписан.

Всего записей: 460 | Зарегистр. 27-06-2005 | Отправлено: 12:18 02-11-2017
NiXXX



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Есть три таблички.
Связь между таблицами: wtmplt.idptype = ptype.id, wiring.idwtmpl = wtmplt.id.
Надо из таблицы ptype отобрать id по которым нет записей в wiring.
Запилил join... выполняется уже с пол часа. Видать напутал что.
 
P.S. Они же в форумных кодах, если SQL Fiddler сдохнет: ptype, wtmplt, wiring.

Всего записей: 318 | Зарегистр. 06-05-2003 | Отправлено: 12:38 16-11-2017 | Исправлено: NiXXX, 18:30 16-11-2017
Dronton2

Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
NiXXX
А как выглядит запрос, который выполняется полчаса? Сколько записей в этих таблицах? какие индексы?

Код:
SELECT *
  FROM ptype
 WHERE id NOT IN (
   SELECT wt.idptype
     FROM wtemplate wt, wiring wi
    WHERE wi.idwtmplt = wt.id)


Всего записей: 460 | Зарегистр. 27-06-2005 | Отправлено: 10:04 17-11-2017
NiXXX



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Сколько записей в этих таблицах? какие индексы?

Записей много от слова ОЧЕНЬ!
Индексы: в wiring индексируются id и IDWTMPL, в wtmplt id и IDPTYPE, в ptype id.
Твой запрос запустил и забыл о нем на два часа... все еще выполняется
 
P.S. Возьму интеграл по частям.

Всего записей: 318 | Зарегистр. 06-05-2003 | Отправлено: 13:50 17-11-2017 | Исправлено: NiXXX, 14:39 17-11-2017
yurkesha



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
del - фигню написал
 
Добавлено:
чтоб зря пост не пропадал: а если
Код:
SELECT wt.idptype
в подзапросе заменить на
Код:
SELECT DISTINCT wt.idptype
время выполнения не сокращается?
 
Добавлено 2: или через один JOIN(но с подзапросом)
Код:
SELECT *
FROM ptype
LEFT JOIN (SELECT DISTINCT wtmplt.idptype AS id
FROM wtmplt, wiring
WHERE wiring.idwtmplt = wtmplt.id) AS subq1
ON ptype.id = subq1.id
WHERE subq1.id IS NULL


Всего записей: 2451 | Зарегистр. 15-12-2003 | Отправлено: 20:02 19-11-2017 | Исправлено: yurkesha, 10:39 20-11-2017
NiXXX



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Потестил - с DISTINCT выполняется быстрее.

Всего записей: 318 | Зарегистр. 06-05-2003 | Отправлено: 11:04 20-11-2017 | Исправлено: NiXXX, 11:09 20-11-2017
yurkesha



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
NiXXX
порядок "быстрее"  какой?
И нет ли раскладки(плюс-минус порядок) соотношения количества записей в таблицах(относительно друг-друга).

Всего записей: 2451 | Зарегистр. 15-12-2003 | Отправлено: 11:11 20-11-2017
NiXXX



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
C distinct - 4:15, без - 4:27.

Всего записей: 318 | Зарегистр. 06-05-2003 | Отправлено: 15:07 20-11-2017
yurkesha



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
NiXXX
это часы:минуты? Грустно...  
С JOIN должно быть еще дольше... Давай тогда примерный расклад по количеству строк во всех таблицах - а-ля: сравнимо, больше-меньше в 10x раз - может запрос с другой стороны убыстрить удастся...
И кстати - а подзапрос долго выполняется?
 
Добавлено:
Смысл может быть в следующем - допустим в таблице wiring уникальных значений idwtmplt на порядки меньше чем общее число записей - в таком случае явно эффективней будет саму таблицу заменить на подзапрос с выборкой уникальных значений idwtmplt. С таблицей wtmplt аналогично.

Всего записей: 2451 | Зарегистр. 15-12-2003 | Отправлено: 19:26 20-11-2017
Dronton2

Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Записей много от слова ОЧЕНЬ!

Цитата:
C distinct - 4:15, без - 4:27.
При таком раскладе, может быть поискать решение в другой плоскости? Например, создать материализованное представление?

Всего записей: 460 | Зарегистр. 27-06-2005 | Отправлено: 10:20 21-11-2017 | Исправлено: Dronton2, 10:20 21-11-2017
Mic777

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
NiXXX

Цитата:
Есть три таблички.  
Связь между таблицами: wtmplt.idptype = ptype.id, wiring.idwtmpl = wtmplt.id.  
Надо из таблицы ptype отобрать id по которым нет записей в wiring.

 
Как такой вариант?

Код:
 
select p1.id
  from PTYPE p1
minus
select distinct p2.id
  from PTYPE p2
  join WTEMPLATE w on w.idptype = p2.id
  join WIRING g on g.idwtmplt = w.id
 

Всего записей: 80 | Зарегистр. 15-12-2005 | Отправлено: 11:19 21-11-2017
yurkesha



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Mic777
перед таким вариантом обычно приходится уточнять тип и версию СУБД...
Ну и по быстродействию (на оракле) MINUS и LEFT JOIN сравнимы для простых выборок(как в данной ситуации).

Всего записей: 2451 | Зарегистр. 15-12-2003 | Отправлено: 12:07 21-11-2017
Mic777

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
yurkesha

Цитата:
перед таким вариантом обычно приходится уточнять тип и версию СУБД...  

Вообще автор вопроса ранее уже писал/уточнял:

Цитата:
Продолжаю упражнения с ораклом

 
А насчет:

Цитата:
Ну и по быстродействию (на оракле) MINUS и LEFT JOIN сравнимы для простых выборок(как в данной ситуации).

думаю никогда не лишним бывает проверить реальные планы разных вариантов, когда занимаешься оптимизацией быстродействия запроса.
К тому же с левым джойном смущает IS NULL в плане использования индексов.
 
А вообще если позволяют требования я бы склонялся к варианту Dronton2:

Цитата:
поискать решение в другой плоскости? Например, создать материализованное представление

 

Всего записей: 80 | Зарегистр. 15-12-2005 | Отправлено: 13:20 21-11-2017 | Исправлено: Mic777, 13:24 21-11-2017
NiXXX



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Комрады, всем +100500 в карму!
Задача разовая, так что делать представление не имеет смысла.

Всего записей: 318 | Зарегистр. 06-05-2003 | Отправлено: 13:44 21-11-2017
yurkesha



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
NiXXX
не расслабляй камрадов - теория должна быть многократно перепроверена практикой! И найти оптимальный метод для этой ситуации - это плюс в копилку доступных методов оптимизации

Всего записей: 2451 | Зарегистр. 15-12-2003 | Отправлено: 13:57 21-11-2017
Mic777

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
NiXXX
мы тут серваки троллим, а он
Цитата:
Задача разовая

мог бы и подождать пару дней результата

Всего записей: 80 | Зарегистр. 15-12-2005 | Отправлено: 13:58 21-11-2017
Открыть новую тему     Написать ответ в эту тему

Страницы: 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

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » SQL запрос

Имя:
Пароль:
Сообщение

Для вставки имени, кликните на нем.

Опции сообщенияДобавить свою подпись
Подписаться на получение ответов по e-mail
Добавить тему в личные закладки
Разрешить смайлики?
Запретить коды


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.Board
© Ru.Board 2000-2018

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru