Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
.NET 4.x

Как опитмально поступить в передаче состояния у наследников (foreignkey)

03.06.2021, 08:59. Показов 3995. Ответов 55

Студворк — интернет-сервис помощи студентам
Всем доброе утро!!!

Представим вот такую задачу.

Есть некая онлайн школа допустим программирования.
В ней есть несколько курсов по разным ЯП (таблица Course).
Есть студенты (таблица Student), которые могут состоять ТОЛЬКО в одном курсе. То есть ТОЛЬКО один язык.
В кажом курсе может быть до 1000 студентов.

Есть структура базы
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE TABLE `Course` (
    `Id` INT(11) NOT NULL AUTO_INCREMENT,
    `Name` VARCHAR(50) NOT NULL,
    `Status` INT(11) NOT NULL
);
 
 
 
CREATE TABLE `Student` (
    `Id` INT NOT NULL AUTO_INCREMENT,
    `Name` VARCHAR(50) NOT NULL,
    `Status` INT NOT NULL,
    `CourseId` INT NOT NULL,
    CONSTRAINT `FK_course` FOREIGN KEY (`CourseId`) REFERENCES `Course` (`Id`)
);

У каждого студента есть свой статус/состояние учёбы в этом курсе.
Статусов ограниченное количество, поэтому они вынесены в код C# в enum, а в базу передаётся только число этого enum для оптимизации работы БД.
Допустим

Принят = 0,
Сдал = 1,
Должник = 2,
Не Сдал = 3,
Отсутствовал = 4,

Так вот задача.

В таблицу Course нужно передавать статус от всех студентов.
Вот что я имею в виду:
Есть курс "Программирование C#".
Есть 2 студента в этом курсе.
Вася со статусом "Не Сдал" = 3
Петя со статусом "Сдал" = 1

Нужно установить статус курсу, по самому безотвественному студенту, так как курс не может быть закрыт/закончен (со статусом "Сдал" = 1) до тех пор пока хоть один студент находится в другом состоянии.

Логика должна быть примерно такая:
Если в курсе есть хоть один студент (Student.Status) который в статусе Отсутствовал = 4, то и в Course.Status должно быть Отсутствовал = 4.
Если есть хоть один Student.Status Не Сдал = 3, то и в Course.Status должно быть Не Сдал = 3.
Если есть хоть один Student.Status Должник = 2, то и в Course.Status должно быть Должник = 2.
Если есть хоть один Student.Status Сдал = 1, то и в Course.Status должно быть Сдал = 1.
Если есть хоть один Student.Status Принят = 0, то и в Course.Status должно быть Принят = 0.

Данные в таблице по студентам обновляются каждый час.
То есть каждый час, после обновления таблицы Student нужно проверять статусы наследников, и устанавливать новые статусы в таблицу Course.

Данных в таблице (Student) будет более 10млн. И данных в таблице (Course) будет больше 1млн.

Как это сделать с минимальной выгрузкой всех данных в программу?

Или ещё лучше как сформировать запрос SQL чтобы это всё происходило на стороне СУБД, без получения данных в программу.
Или может SQL запрос который получает полуобработанные данные вида:
CourseId - Status(уже проверенный)

Или может уже существует подход к такой задаче.

p.s. Используется MySQL база и библиотека linq2db.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
03.06.2021, 08:59
Ответы с готовыми решениями:

Фильтрация ForeignKey поля по другому ForeignKey полю в админке
Всем привет, форумчане и джангисты в частности. Нужна ваша помощь. Свой пример приводить не буду, т.к. слишком много лишнего, но на...

Как добавить ключ FOREIGNKEY в таблицу?
Установила денвер-3,на английском.В MySql создала таблицу.Не могу никакими судьбами,туплю,добавить ключ FOREIGKEY.кТО СКАЖЕТ,как его...

Как правильно указать default для ForeignKey?
class vedModel(models.Model): # прикрепит к базовому объекту профиля base_id = models.ForeignKey('account.profileModel',...

55
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
03.06.2021, 18:40
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Igr_ok Посмотреть сообщение
в 6 ТС объяснил, почему одного поля статус недостаточно
В [13] был предложен вариант без доп.таблицы , которая и в самом деле не нужна от слова совсем.
Цитата Сообщение от Igr_ok Посмотреть сообщение
А на троллинг я не ведусь
Какой троллинг ? Вопросы были заданы совершенно серьезно.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
03.06.2021, 19:04
Цитата Сообщение от MsGuns Посмотреть сообщение
В [13] был предложен вариант без доп.таблицы , которая и в самом деле не нужна от слова совсем.
Но TC добавил условие, что приоритет Статусов не соответствует их численным значениям.
Как в таком случае сервер будет их обрабатывать без таблицы Статус-Приоритет?
1
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
03.06.2021, 19:29
Элд Хасп, "Статусов" всего пять. Почему бы сразу не выстроить их по приоритетам ? Тем более, что в интерфейсе вместо статусов будет отображаться из смысловой эквивалент - текст.
Зачем городить огород ради одной грядки, то бишь вытащенного с потолка "приоритета" ?
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
03.06.2021, 19:31
Цитата Сообщение от MsGuns Посмотреть сообщение
"Статусов" всего пять. Почему бы сразу не выстроить их по приоритетам ?
Ну, это вопрос не ко мне.
Это условие от ТС:
Цитата Сообщение от BeginnerCoderCS Посмотреть сообщение
Так как в будущем может измениться логика наследования статуса, и порядок важности статусов будет другим.
То есть без привязки возрастания числа.
1
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
03.06.2021, 22:49  [ТС]
Цитата Сообщение от MsGuns Посмотреть сообщение
Мне трудно представить не веб систему, в которой одновременно работают десятки тысяч реальных юзеров.
Пример с курсами и юзерами, как уже говорил, для примера.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
BeginnerCoderCS, просто такое обновление (очень редкое и большими пакетами) довольно не типично и несклоько ставит в тупик, как уже заметил MsGuns.
Данные будут получаться с удалённого ограниченного API на количество запросов, и изменения будут зеркалиться в свою БД для дальнейшей работы.
Данные периодически будут добавляться (Insert) не только (Update).


Итого минимум данных в таблице (Student) будет более 10млн. И данных в таблице (Course) будет больше 1млн.
Со временем максимум планируется (может за год) (Student) около 30млн. И (Course) около 15млн.

Программы-клиенты, которые будут использовать базу, чаще всего будут получать данные именно из таблицы Course.
И если каждый раз при получении пересчитывать статус от Student то будет слишком накладно.
Вот поэтому думаю, что лучше статус присвоить при самом получении изменений в Student.
Таблицу Student программы клиенты будут использовать редко. А Course часто.


Цитата Сообщение от Igr_ok Посмотреть сообщение
раз в час. А извлечение данных запросом будет только тогда, когда эти данные кому-то понадобятся. Что вам подсказывает здравый смысл?)
Надеюсь описание этого поста чуть выше, отвечает на этот вопрос.

Цитата Сообщение от MsGuns Посмотреть сообщение
Если утверждение о сотнях тысяч в час изменений в БД (в чем я сильно сомневаюсь, разве что речь идет об автоматических процессах) верно и "тормоза" все же появятся, то с ними (тормозами) опять же можно успешно побороться, навесив на поле минимального статуса в таблице курсов вторичный индекс. При условии длинных текстов в остальных полях таблицы курсов это даст ускорение выборки в разы, а то и на порядок.
Со вторичным индексом пожалуйста подробнее.


Цитата Сообщение от MsGuns Посмотреть сообщение
О каком вычисляемом поле идет речь ? Min по всем студентам данного курса ?
Цитата Сообщение от MsGuns Посмотреть сообщение
Элд Хасп, "Статусов" всего пять. Почему бы сразу не выстроить их по приоритетам ? Тем более, что в интерфейсе вместо статусов будет отображаться из смысловой эквивалент - текст.
Зачем городить огород ради одной грядки, то бишь вытащенного с потолка "приоритета" ?

Статусов не пять, их гораздо больше. Нельзя использовать вычисление по возрастанию. (это только в примере)
На текущий момент нужна определённая передача статусов от Student к Course. В дальнейшем добавятся дополнительные, или заказчик скажет, что нужно изменить логику, и присваивать с другими приоритетами. То есть к порядковому числу enum привязываться категорически нельзя.
И приоритет там не с потолка.

Смотрю в сторону триггеров, но к сожалению ещё с ними не работал (
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
03.06.2021, 23:16
Цитата Сообщение от BeginnerCoderCS Посмотреть сообщение
Статусов не пять, их гораздо больше.
Я думаю вам нужно добавить дополнительную таблицу Курс-Статус-Колво.
При изменении таблицы Студентов хранимые процедуры будут вносить изменения в эту таблицу.
Тогда программа-клиент может просто запросить все статусы этого курса и локально обработать их как ей нужно.
Будет гораздо проще извлечь любую требуемую информацию.
Чем потом под каждый вероятный вид запроса придумывать как его оптимально сделать и, возможно, менять структуру БД.
1
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
03.06.2021, 23:35
Цитата Сообщение от BeginnerCoderCS Посмотреть сообщение
Статусов не пять, их гораздо больше
Вот оптимальное решение !
ХП, вызываемая триггером изменения-добавления "студента", просто извлекает статус из "курса" этого "студента", заодно получая "приоритет". "Приоритеты" "студента" и "курса" сравниваются и, если возникает потребность замены "статуса" в "курсе", выполняется апдейт "курса.
Никаких min, три короткие операции : 1) извлечение "приоритета" из "статуса" "студента" (1 запись), 2) извлечение из двух связанных таблиц "курсов" и "справочника приоритетов" действующего "приоритета" и, возможно, 3) апдейт "статуса" в таблице "курсов".
1
Эксперт .NET
 Аватар для Usaga
14147 / 9375 / 1351
Регистрация: 21.01.2016
Сообщений: 35,319
04.06.2021, 05:52
Я вот из обсуждения не понял на кой тут нужен триггер, который будет срабатывать при каждой вставке строки для вычисления данных, которые понадобятся раз в хрен знает сколько?

Такие вещи нужно вычислять только когда они реально нужны, а не на каждый чих. Если такие запросы более-менее частые, а актульностью данных можно немного поступиться, то можно завести summary table, куда временно складывать результаты вычислений.

Но триггер для этого внатуре перебор.

Цитата Сообщение от MsGuns Посмотреть сообщение
Во-первых триггеры сами по себе работают ну ооочень быстро. 1млн срабатываний займет несколько сек.
Вот с этим я поспорю. Вызов триггре, даже полупустого, сам по себе уже значительно скажется на скорости запроса. А если в триггере ещё и выборки какие-то происходят, то вообще базу положит. Я такое уже видел и там был не миллион записей.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
04.06.2021, 06:48
Цитата Сообщение от Usaga Посмотреть сообщение
Я вот из обсуждения не понял на кой тут нужен триггер, который будет срабатывать при каждой вставке строки для вычисления данных, которые понадобятся раз в хрен знает сколько?
Из разъяснений TC:
Цитата Сообщение от BeginnerCoderCS Посмотреть сообщение
Данные будут получаться с удалённого ограниченного API на количество запросов, и изменения будут зеркалиться в свою БД для дальнейшей работы.
Данные периодически будут добавляться (Insert) не только (Update).
Итого минимум данных в таблице (Student) будет более 10млн. И данных в таблице (Course) будет больше 1млн.
Со временем максимум планируется (может за год) (Student) около 30млн. И (Course) около 15млн.
Программы-клиенты, которые будут использовать базу, чаще всего будут получать данные именно из таблицы Course.
И если каждый раз при получении пересчитывать статус от Student то будет слишком накладно.
Вот поэтому думаю, что лучше статус присвоить при самом получении изменений в Student.
Таблицу Student программы клиенты будут использовать редко. А Course часто.
Я плохо знаю БД.
Такое обновление (Update + Insert) - это одна операция (транзакция) или нет?
И можно ли в БД вызвать автообновление связанных данных не вовремя этой операции, а после неё?
Или такое автообновление должно быть вызвано внешним кодом (как изначально и предполагал TC)?
1
Эксперт .NET
 Аватар для Usaga
14147 / 9375 / 1351
Регистрация: 21.01.2016
Сообщений: 35,319
04.06.2021, 07:12
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Такое обновление (Update + Insert) - это одна операция (транзакция) или нет?
Завернут в транзакцию - будет одна)

Цитата Сообщение от Элд Хасп Посмотреть сообщение
И можно ли в БД вызвать автообновление связанных данных не вовремя этой операции, а после неё?
Можно. Называется JOB. Не все СУБД такое поддерживают. Но это уже вопрос отложенной работы. А значит актуальность данных будет страдать. Допустимо ли такое надо отдельно у ТС узнавать.

Вообще, я крайне против триггеров. Только когда иначе ну совсем никак, тогда только допускаю их использование.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
04.06.2021, 07:19
Цитата Сообщение от Usaga Посмотреть сообщение
А значит актуальность данных будет страдать.
Судя по объяснениям TC, на время обновления БД должна отключаться от других операций.
По крайней мере я так понял.

Добавлено через 1 минуту
Исходя из топика, вопрос TC был такой: Как после обновления БД оптимально составит SQL запрос по обновлению связанных данных, чтобы минимизировать выгрузку данных из БД.
1
Эксперт .NET
 Аватар для Usaga
14147 / 9375 / 1351
Регистрация: 21.01.2016
Сообщений: 35,319
04.06.2021, 08:18
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Судя по объяснениям TC, на время обновления БД должна отключаться от других операций.
Но... зачем? О_о

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Как после обновления БД оптимально составит SQL запрос по обновлению связанных данных, чтобы минимизировать выгрузку данных из БД.
А тут и не нужна выгрузка, если вопрос только в обновлении статусов.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
04.06.2021, 08:24
Цитата Сообщение от Usaga Посмотреть сообщение
Но... зачем? О_о
Зачем....
Ну, так я понял из объяснений.
Идёт пакетное обновление очень большого количества записей - то есть может занимать какое-то время хотя бы просто на передачу данных.
После этого обновления в БД связанных данных - тоже какое-то время. Тем более что счёт идёт на миллионы засей.

И всё это время данные в БД могут быть не в полной мере корректными.
1
Эксперт .NET
 Аватар для Usaga
14147 / 9375 / 1351
Регистрация: 21.01.2016
Сообщений: 35,319
04.06.2021, 08:29
Цитата Сообщение от Элд Хасп Посмотреть сообщение
И всё это время данные в БД могут быть не в полной мере корректными.
Чтобы этого не было и придумали транзакции) Особенно с высоким уровнем изоляции)
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
04.06.2021, 08:30
Цитата Сообщение от Usaga Посмотреть сообщение
если вопрос только в обновлении статусов.
Да.
Только в них.
И как я понял по дальнейшим разъяснениям BeginnerCoderCS, нужный статус (приоритетность?) по сути определяется динамически.
Вот насколько динамически - он уже не уточнил.

Если однократно при обновлении БД (раз в час), то, наверное, нужна какая-то таблица приоритетов.
Если нужна возможность каждому клиенту самому определять какую информацию ему запрашивать, то лучше сделать таблицу Курс-Статус-Количество.
Статусов много.
Но это "много" от силы 10-20.
Поэтому вернуть клиенту по запросу такую небольшую табличку - это совершенно не затратно.
А уже в клиенте он пусть как хочет её вертит.


BeginnerCoderCS, уточните пожалуйста этот момент.
0
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
04.06.2021, 08:32  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Я думаю вам нужно добавить дополнительную таблицу Курс-Статус-Колво.
При изменении таблицы Студентов хранимые процедуры будут вносить изменения в эту таблицу.
Тогда программа-клиент может просто запросить все статусы этого курса и локально обработать их как ей нужно.
А получение новых данных с API ограничено не мной, а самим апи. То есть я не могу оттуда постоянно дёргать эти данные.
Вот и выходит, что лучше после одновления, сразу пересчитать все статусы.
А получение программой-клиентом этих данных (как раз по статусу) получается часто, и каждый раз обрабатывать одни и те же данные (а они могли не меняться несколько дней) будет затратно.

Если смотреть пример, то в таблице Course будут много курсов которые уже закончились и стоят со статусом "Сдан".
А такие курсы программе-клиенту если и нужны, то крайне редко.
А если постоянно дёргать их и пересчитывать, то получится что постоянно придётся брать ВСЮ таблицу Course и постоянно делать одну и ту же операцию по присвоению статуса, независимо от того, были ли изменения у наследников (Student).


Цитата Сообщение от Usaga Посмотреть сообщение
Такие вещи нужно вычислять только когда они реально нужны, а не на каждый чих. Если такие запросы более-менее частые, а актульностью данных можно немного поступиться, то можно завести summary table, куда временно складывать результаты вычислений.
Поступиться немного можно.
Если я правильно понял summary table, то статус переданный в Course на основе статусов из таблицы Student это уже и есть в каком-то смысле summary table.


Цитата Сообщение от Usaga Посмотреть сообщение
Вызов триггре, даже полупустого, сам по себе уже значительно скажется на скорости запроса. А если в триггере ещё и выборки какие-то происходят, то вообще базу положит. Я такое уже видел и там был не миллион записей.
Вот и я боюсь за триггер на таком объёме данных.

Цитата Сообщение от Usaga Посмотреть сообщение
Называется JOB.
Это вы имеете в виду EVENT в MySQL?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Судя по объяснениям TC, на время обновления БД должна отключаться от других операций.
Нет, отключаться нельзя, так как данные из Course получаются регулярно.
Старыми статусами приходится пренебрегать до момента получения новых, но это ограничение апи, и ничего с этим не поделать.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Исходя из топика, вопрос TC был такой: Как после обновления БД оптимально составит SQL запрос по обновлению связанных данных, чтобы минимизировать выгрузку данных из БД.
Мне это показалось минимально затратным по ресурсам.
1. Получили обновления из апи в Student
2. Пересчитали все статусы и передали родителю в Course
3. Все программы счастливы получают курсы типа
SQL
1
SELECT * FROM Course WHERE STATUS = 4;
А из 1млн записей в Course с таким статусом только 300к записей, а не 1млн.


Но с таким объёмом на регулярной основе я не работал, поэтому и спрашиваю как лучше поступить.
Были большие базы, но я оттуда только получал данные, а не добавлял.


С триггером проще это сделать, так как в изменяемой или добавляемой записи обязательно есть Student.CounterId, по которому можно получить и все Student.Status и обновить этот статус в Counter.Status, но нагрузка мне кажется будет большой.

А вот без триггера (даже с меткой времени) придётся перебирать всё в цикле

Вот мысль про метку времени обновления:

Если добавить в Student дополнительное поле TimeStamp и вписывать время последнего изменения, то по этому изменению можно будет пересчитывать ТОЛЬКО те строки, в которых были изменения за прошедший час.

Типа получить все Student.CounterId в которых Student.TimeStamp > указанной даты.
Затем проверять Student.Statusпо указанным Student.CounterId и передавать уже их в Course.Status

Но это всё в цикле, а если в цикле, то наверное это придётся делать на уровне приложения, а не в самой СУБД.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
04.06.2021, 08:37
В моём понимании, нужна БД для таких сущностей
C#
1
2
3
4
5
6
public class Course
{
    public int Id;
    public string Name;
    public int Status;
}
C#
1
2
3
4
5
6
7
public class Student
{
    public int Id;
    public string Name;
    public int Status;
    public int CourseId;
}
C#
1
2
3
4
5
6
public class CourseStatus
{
    public int CourseId;
    public int Status;
    public int Count;
}
В таблице Students ОБЯЗАТЕЛЬНО вторичный индекс по сочетанию CourseId и Status.
1
 Аватар для Andrey-MSK
3339 / 2226 / 387
Регистрация: 14.08.2018
Сообщений: 7,517
Записей в блоге: 4
04.06.2021, 08:38
BeginnerCoderCS, я как-то давно сваял хранимку для MS SQL Server 2008, которая рассчитывает и записывает статусы поставки по позициям спецификации и статусы поставки заявки полностью в зависимости от того, сколько материала присутствует на складе. Работает вроде шустро, по крайней мере тормозов пока не заметил Вдруг будет полезно, может как-то переделаете для себя
T-SQL
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
ALTER PROC [dbo].[spOMTOCheckStatus](@posQty int OUTPUT, @posQtyZ int OUTPUT)
AS
BEGIN
    DECLARE @idZPos         int -- ID позиции спецификации заявки
    DECLARE @idZ            int -- ID заявки
    DECLARE @sumStor        float
    DECLARE @posEI1Z        float
    DECLARE @allPos         int
    DECLARE @allPosZ        int
    DECLARE @currentPos     int
    DECLARE @currentPosZ    int
    DECLARE @counter        int
    DECLARE @counterZ       int
    DECLARE @countSpecAll   int -- Количество позиций спецификации
    DECLARE @countSpecSet   int -- Количество позиций спецификации со статусом Поставлено
    DECLARE @countSpecProg  int -- Количество позиций спецификации со статусом Идет поставка
    DECLARE @countSpecNot   int -- Количество позиций спецификации со статусом Поставки нет
    -- Табличные переменные для прохода в цикле WHILE
    -- @idTable - табличная переменная, которая хранит ID позиций спецификации заявок
    DECLARE @idTable        TABLE (ID int NOT NULL PRIMARY KEY IDENTITY(1, 1), PosZDet int)
    -- @idTableZ - табличная переменная, которая хранит ID заявок
    DECLARE @idTableZ       TABLE (ID int NOT NULL PRIMARY KEY IDENTITY(1, 1), ZIDNum int)
 
    -- Отсекаются позиции спецификации со статусом Поставлено
    SELECT @counter = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [Status] = N'Поставлено'
 
    IF @counter > 0
        INSERT INTO @idTable ([PosZDet]) SELECT [ID_ZayavkaPod] FROM [dbo].[tblOMTOZDetails] WHERE [Status] <> N'Поставлено'
    ELSE
        INSERT INTO @idTable ([PosZDet]) SELECT [ID_ZayavkaPod] FROM [dbo].[tblOMTOZDetails]
    SET @allPos = @@ROWCOUNT
 
    -- Организация прохода по позициям спецификации с обновлением статуса в зависимости от условия
    SET @currentPos = 0
    WHILE @currentPos < @allPos
        BEGIN
            SET @currentPos = @currentPos + 1
            SELECT @idZPos = [PosZdet] FROM @idTable WHERE [ID] = @currentPos
            SELECT @sumStor = ISNULL(SUM([KolEI1]), 0) FROM [dbo].[tblOMTOStorageIn] WHERE [ID_ZayavkaPod] = @idZPos 
            SELECT @posEI1Z = [KolvoEI1] FROM [dbo].[tblOMTOZDetails] WHERE [ID_ZayavkaPod] = @idZPos
            UPDATE [dbo].[tblOMTOZDetails] SET [Status] = 
                    CASE
                        WHEN @sumStor >= @posEI1Z THEN N'Поставлено'
                        WHEN @sumStor > 0 AND @sumStor < @posEI1Z THEN N'Идет поставка'
                        ELSE N'Поставки нет'
                    END
                WHERE [ID_ZayavkaPod] = @idZPos 
        END
 
    -- Отсекаются заявки со статусом Поставлено
    SELECT @counterZ = COUNT(*) FROM [dbo].[tblOMTOZayavka] WHERE [Status] = N'Поставлено'
 
    IF @counterZ > 0
        INSERT INTO @idTableZ ([ZIDNum]) SELECT [ID_Zayavka] FROM [dbo].[tblOMTOZayavka] WHERE [Status] <> N'Поставлено'
    ELSE
        INSERT INTO @idTableZ ([ZIDNum]) SELECT [ID_Zayavka] FROM [dbo].[tblOMTOZayavka]
    SET @allPosZ = @@ROWCOUNT
 
    -- Организация прохода по номерам заявок с обновлением статуса в зависимости от статуса позиций спецификации заявки
    SET @currentPosZ = 0
    WHILE @currentPosZ < @allPosZ
        BEGIN
            SET @currentPosZ = @currentPosZ + 1
            SELECT @idZ = [ZIDNum] FROM @idTableZ WHERE [ID] = @currentPosZ
            SELECT @countSpecAll = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ
            SELECT @countSpecSet = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ AND [Status] = N'Поставлено'
            SELECT @countSpecProg = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ AND [Status] = N'Идет поставка'
            SELECT @countSpecNot = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ AND [Status] = N'Поставки нет'
            UPDATE [dbo].[tblOMTOZayavka] SET [Status] = 
                CASE
                    WHEN @countSpecAll = @countSpecSet THEN N'Поставлено'
                    WHEN (@countSpecProg > 0 OR @countSpecSet > 0) AND @countSpecSet < @countSpecAll THEN N'Идет поставка'
                    WHEN @countSpecNot = @countSpecAll THEN N'Поставки нет'
                END
            WHERE [ID_Zayavka] = @idZ
        END
    SET @posQty = @allPos -- Количество обработанных записей позиций спецификаций
    SET @posQtyZ = @allPosZ -- Количество обработанных зявок
END
GO
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16129 / 11253 / 2888
Регистрация: 21.04.2018
Сообщений: 33,086
Записей в блоге: 2
04.06.2021, 08:45
BeginnerCoderCS, вы неправильно поняли.
Таблица CourseStatus так же будет считаться однократно при обновлении.
Но клиент по запросу получит все (не нулевые) Статусы нужного курса.
И сам уже решит что ему нужно для анализа.

Добавлено через 2 минуты
Цитата Сообщение от BeginnerCoderCS Посмотреть сообщение
Нет, отключаться нельзя, так как данные из Course получаются регулярно.
Старыми статусами приходится пренебрегать до момента получения новых, но это ограничение апи, и ничего с этим не поделать.
То есть ситуация при которой произошло обновление информации о студентах, но не произошло обновления информации о статусах курсов допустима?

Тогда да, никакого отключения не нужно.

Добавлено через 2 минуты
BeginnerCoderCS, по поводу полной таблицы статусов курсов.
По сути эта информация всё равно будет считаться и вопрос только в том, запомнить её полностью (5-10-20 строк из трёх int полей на каждый курс), или только одну из этих строк.
1
9 / 6 / 3
Регистрация: 10.01.2020
Сообщений: 330
04.06.2021, 08:46  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Но это "много" от силы 10-20.
Да много это около 20, ну может 30 )

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если нужна возможность каждому клиенту самому определять какую информацию ему запрашивать, то лучше сделать таблицу Курс-Статус-Количество.
Клиент в основном только получает данные из Course.


По приоритетам
Допустим текущий приоритет:
Принят = 0
Отсутствовал = 4
Должник = 2
Не Сдал = 3
Сдал = 1

Затем заказчик скажет, что отключаем передачу статуса Принят = 0, и Должник = 2 в Course, Так как по каким-то причинам, теперь не нужны будут эти статусы.

То есть новый приоритет будет
Отсутствовал = 4
Не Сдал = 3
Сдал = 1

Или меняем последовательность
Не Сдал = 3
Отсутствовал = 4
Должник = 2
Принят = 0
Сдал = 1


Эти изменения могут быть, такак заказчик об этом предупредил.
То есть ему не нужно это выводить в интерфейс, это не гибкая настройка, но предупреждение было, что изменения в дальнейшем могут быть, чтобы я не захардкодил этот момент.
С доп таблицей приоритетов мне нравится идея, но что-то я не с той стороны захожу наверное, так как не могу реализовать нормально.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.06.2021, 08:46
Помогаю со студенческими работами здесь

Как правильно отлавливать Constraint ForeignKey в DAO?
Введение: как известно, В БД при соответствующие настроенном ForeignKey constraint при попытке удалить запись (если на неё будут ссылаться...

Как изменить отображение текста ForeignKey в моделе
Здравствуйте, Возможно я не правильно гуглю, но не смог найти нужной мне информации, а опыта допереть до этого самому не хватает...

Как шифровать файлы при передаче на сервер и дешефровать при передаче с сервера на клиент
Есть программа клиент/сервер, файлы со стороны клиента передаются на сервер, если были внесены изменения. Как правильно зашифровать файлы,...

Как сделать каскадный вызов элементов ForeignKey в одной view в Django?
Задача: Вывести статью, в которой будет 3 вопроса (из относящейся модели), в каждом вопросе будет по 3 ответа (уже относящиеся к самому...

Как посмотреть наследников класса
Возможно вопрос задавался на форуме уже, я не нашел. Собственно, есть класс в каком-то пространстве имен. Как посмотреть...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru