Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
eonae Member Откуда: Сообщений: 17 |
Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64) Aug 22 2017 17:04:49 Copyright (C) 2017 Microsoft Corporation Express Edition (64-bit) on Windows 10 Home Single Language 10.0 <X64> (Build 16299: ) Уважаемые знатоки! Довольно нетривиальная (или мне так кажется..) задача. Есть данные посещения занятий в учебном заведении: CREATE TABLE Visits (VisitID [int] IDENTITY(1,1) PRIMARY KEY CLUSTERED, LessonID [int] FOREIGN KEY (ClientID) REFERENCES Clients (ClientID) ClientID [int] FOREIGN KEY (LessonID) REFERENCES Lessons (LessonID) Status [bit] NOT NULL) -- 0 - не был, 1 - был Таблица Client содержит данные об учениках. Таблица Lessons имеет примерно такой вид: CREATE TABLE Lessons (LessonID [int] IDENTITY(1,1) PRIMARY KEY CLUSTERED, UnitID [int] FOREIGN KEY (UnitID) REFERENCES Units (UnitID) -- Unit - есть учебная группа. LessonDate [date] NOT NULL), ....) --Есть ещё поля, но для задачи они не важны. И из этих данных необходимо получить ведомость посещения с за определённый месяц и в определённой группе примерно такого вида:
В общем, как в школьном журнале. В связи с этим два вопроса: 1) Я вполне себе представляю, как я могу переработать информацию из БД, чтобы получить искомую таблицу на стороне клиента (с#). Но может быть можно каким-то образом делать это на стороне сервера? Средствами T-SQL? 2) Возможно, кто-то может посоветовать другую схему таблиц для хранения этих данных, чтобы получить искомый результат было легче? Опыта работы с БД нет, но есть производственная необходимость.. Всё делается по наитию. Буду благодарен не только за готовое решение, но и вообще за любую наводку на плодотворную мысль. Заранее благодарен! С уважением, Сергей. |
|||||||||||||||||||||
6 авг 18, 19:06 [21632015] Ответить | Цитировать Сообщить модератору |
Remind Member Откуда: UK Сообщений: 523 |
Однозначно делать на стороне клиента. Можете и на стороне SQL Server'a, конечно, PIVOT вам в помощь. Просто вы наверняка захотите dynamic pivot, это тоже возможно, но нафиг такой гемор творить на стороне SQL - не совсем понятно. |
6 авг 18, 19:55 [21632070] Ответить | Цитировать Сообщить модератору |
Andy_OLAP Member Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион Сообщений: 3151 |
Таки лучше подумать и написать кошерно. CREATE TABLE Visits (VisitID [int] IDENTITY(1,1) PRIMARY KEY CLUSTERED, LessonID [int] FOREIGN KEY (ClientID) REFERENCES Lessons (LessonID) ClientID [int] FOREIGN KEY (LessonID) REFERENCES Clients (ClientID) Status [bit] NOT NULL) -- 0 - не был, 1 - был Начните со списка Clients, присоединив к нему через cross join выборку ВСЕХ дат из таблицы дат. Ну или до максимальной даты LessonDate для выбранного месяца из таблицы Lessons. А уже потом на пересечении ученика и даты выбирайте нужные значения из Visits. Хотя бы потом, что пересечение ученика и даты может дать несколько разных записей в Lessons - и я никак не пойму, почему Вы в ведомости рисуете 0 и 1. А если уроков должно было быть 5, а ученик посетил только 4? Или Вам нужно, чтобы он посетил хотя бы один урок из выбранной даты? |
|||||||||||||||||||||||
6 авг 18, 20:15 [21632107] Ответить | Цитировать Сообщить модератору |
Andy_OLAP Member Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион Сообщений: 3151 |
Andy_OLAP, Поправлю таки сам себя - присоединив через cross join выборку всех даты выбранного для ведомости месяца. |
6 авг 18, 20:16 [21632109] Ответить | Цитировать Сообщить модератору |
Владимир Затуливетер Member Откуда: Сообщений: 427 |
+1 За то чтобы делать на клиенте. По описанию это вообще обычный сводный отчет, возможно вам нужно просто выбрать "правильный" тип отчета в вашем reporting framework в c#. |
6 авг 18, 21:03 [21632160] Ответить | Цитировать Сообщить модератору |
eonae Member Откуда: Сообщений: 17 |
Большое спасибо за ответы!
Честно говоря, думал побыстрее работать будет. Конечно, когда речь идёт об одной группе и одном месяце - говорить о производительности смешно. Но если нужно в масштабах учебного центра сделать отчёт - 40 групп за год, скажем.. PIVOT вообще не в курсе - буду гуглить..
На самом деле, может быть название Visits не совсем корректно по смыслу. Имеется ввиду статус занятия для данного ученика: Null - не заполнено, 0 - отсутствовал, 1 - присутствовал.. там ещё будет статусы: оплачиваемый пропуск, неоплачиваемый и много чего ещё. Записи в Visits генерируются автоматически при появлении записи в таблице Lessons, для каждого клиента, привязанного к данной группе. И дальше неважно, пока его "не отвязать", записи для него генерятся, хоть даже его ни разу не было на занятии. Наверное немного путанно объяснил.. С cross join поэкспериментирую обязательно.
Большое спасибо за наводку. В с# я пока тоже не гуру далеко )). Думал "ручками" делать. Буду смотреть! |
||||||
6 авг 18, 21:47 [21632204] Ответить | Цитировать Сообщить модератору |
Wlr-l Member Откуда: Сообщений: 523 |
eonae, Пусть в группе 30 человек, в месяце 30 дней, т.е. из таблицы Visits нужно взять 30*30=900 строк и развернуть. Пусть еще и 40 групп. Если это гемор, то что тогда не гемор? С одной строны "Status [bit] NOT NULL) -- 0 - не был, 1 - был", с другой стороны "Null - не заполнено, 0 - отсутствовал, 1 – присутствовал" "Записи в Visits генерируются автоматически при появлении записи в таблице Lessons, для каждого клиента, привязанного к данной группе". Действительно, "немного путанно", Lessons – это расписание занятий, формируется один раз в начале семестра, с возможной коррекцией в течение семестра, а Visits заполняется после каждого занятия в соответствии с реальной посещаемостью. Не важно каким способом. |
7 авг 18, 14:30 [21632952] Ответить | Цитировать Сообщить модератору |
982183 Member Откуда: VL Сообщений: 3374 |
Отчет всегда будет выдаваться за календарный месяц? Или возможна выборка за несколько месяцев? |
||
7 авг 18, 14:46 [21632977] Ответить | Цитировать Сообщить модератору |
Remind Member Откуда: UK Сообщений: 523 |
Для меня гемор - это решать задачи тулзами, которые для этого не предназначены. Да пусть там хоть 1 строка, писать динамический pivot ради этого считаю нецелесообразным. Это как решать data science задачи на чистом T-SQL без использования python и т.п. |
||
7 авг 18, 17:37 [21633215] Ответить | Цитировать Сообщить модератору |
komrad Member Откуда: Сообщений: 5498 |
можно не динамический, а вполне статический, если "необходимо получить ведомость посещения с за определённый месяц да и группу, можно отображать, при желании пример с тестовыми данными внизу идея в том, чтобы выдавать пивотом посещения за следующие 31 день, начиная с интересующей даты
|
||||
7 авг 18, 18:42 [21633343] Ответить | Цитировать Сообщить модератору |
eonae Member Откуда: Сообщений: 17 |
В итоге сделал всё-таки на c#. Работает хорошо, вполне быстро даже при выгрузке всей информации за год. Но за новый импульс в изучении sql всем большое спасибо! |
8 авг 18, 10:46 [21633984] Ответить | Цитировать Сообщить модератору |
Wlr-l Member Откуда: Сообщений: 523 |
Пример статического запроса уже привели. Приведу пример динамического запроса:
Для мышки(Wlr-l) кошка (python) страшнее зверя нет! Проблема использования тех или иных языков для решения тех или иных задач сводится к известной проблеме Мастера и подмастерья. Мастер с помощью молотка и зубила (чистый T-SQL) может сделать то, что подмастерье не сможет сделать даже с помощью станков (python). |
|||||
8 авг 18, 14:36 [21634444] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |