SQL - столбцы для разных категорий
Я новичок в SQL. У меня есть база данных с данными для разных экзаменов, например:
Student Test Grade
--------------------
St1 T1 A
St2 T1 B
St3 T1 B
St1 T2 B
St2 T2 B
St3 T2 A
St1 T3 A
St2 T3 C
St3 T3 B
Затем я хотел бы распечатать отчет с использованием тестов (T1, T2 и T3) в качестве столбцов:
Student T1 T2 T3
----------------------
St1 A B A
St2 B B C
St3 B A B
Я пробовал разные вещи, но я зациклился на том, как производить такую распечатку. Любая помощь приветствуется!
Ответы
Ответ 1
Использование:
SELECT t.student,
MAX(CASE WHEN t.test = 'T1' THEN t.grade END) AS T1,
MAX(CASE WHEN t.test = 'T2' THEN t.grade END) AS T2,
MAX(CASE WHEN t.test = 'T3' THEN t.grade END) AS T3
FROM TABLE t
GROUP BY t.student
Ответ 2
Я попросил повторить аналогичную question. Вам нужно что-то похожее на сводную таблицу, но это невозможно в SQLite (насколько я знаю).
Ответ 3
Я считаю, что если вы собираетесь расширить эту систему, чтобы включить в нее больше информации, вы могли бы воспользоваться переработкой своей базы данных, я бы построил ее так:
Имя таблицы= Полужирный
Название столбца = курсив
Студенты
- SID (первичный ключ)
- Другая информация о студенте
Испытания
- TID (первичный ключ)
- Другая информация о тесте
Тест-классы
- GID (первичный ключ)
- TID (внешний ключ)
- SID (внешний ключ)
- Оценка
Эта структура основана на идее, которая называется нормализацией базы данных (вы получите много информации, если вы ее найдете в Google). Я дам вам частичное резюме ниже, но если вы собираетесь делать много SQL, вы должны сами прочитать его:
Первое, что нужно знать, это то, что первичный ключ - это только уникальный идентификатор, он обычно не является частью информации (однако, поскольку он уникален, каждая базовая точка должна иметь разное значение для своего первичного ключа) и внешний ключ это способ ссылки на строку в одной таблице из строки в другой таблице с использованием первичного ключа ссылки: например, здесь SID внешнего ключа в каждом классе ссылается на одного ученика на основе их SID первичного ключа.
например. у ученика есть SID 1, и все его тесты имеют 1 в столбце SID. для учащихся 2, 3, 4 и т.д.
Основная идея нормализации состоит в том, что все уникальные данные сохраняются только один раз, а затем ссылаются на другие места, которые его используют (если вы посмотрите, как структурированы ключи в этом примере, вся информация о студенте хранится в таблицу, а затем ссылаются в своих тестах, а не дублируются в каждом классе).
Чтобы получить то, что вы хотите от этих таблиц, я бы использовал это (написанное на PHP):
$sql = 'SELECT * FROM Tests ORDER BY TID';
$tempresult = mysql_query($sql);
while($temprow = mysql_fetch_array($tempresult)){
echo $temprow['TID'];
}
$sql = 'SELECT * FROM Students';
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)){
echo '\n'.$row['SID'];
$sql = 'SELECT * FROM Grades WHERE SID='.$row['SID'].' ORDER BY TID';
$result2 = mysql_query($sql);
while($row2 = mysql_fetch_array($result2)){
echo ' '.$rows['Grade'];
}
}
Вы можете добавить к этому форматирование в операторах эха, а также распечатать любую дополнительную информацию, которую вы хотите добавить. Если у вас есть какие-либо вопросы, спросите их.
РЕДАКТИРОВАТЬ: Я прочитал другие и согласен с тем, что их метод, по всей вероятности, превосходит, единственное, что я не уверен в том, могут ли сводные таблицы расширяться, чтобы обрабатывать различное количество тесты, если это возможно (или вам не нужно), то я предлагаю их метод, иначе я чувствую, что это может иметь место в вашем приложении.
Ответ 4
Существует несколько способов сделать это, оба из которых (в чистом SQL, а не в коде, генерирующем команду SQL) требуют, чтобы количество столбцов было известно и исправлено. Наиболее простой способ реализации:
SELECT eg.Student,
(SELECT Grade from ExamGrade eg1 WHERE eg1.Student = eg.Student AND Test = 'T1') AS T1
(SELECT Grade from ExamGrade eg2 WHERE eg2.Student = eg.Student AND Test = 'T2') AS T2
(SELECT Grade from ExamGrade eg3 WHERE eg3.Student = eg.Student AND Test = 'T3') AS T3
FROM ExamGrade eg
Это будет работать практически в любой среде, включая SQLite, и может быть немного более изящным со скалярной функцией GetTest(), которая будет принимать учащийся и номер теста и возвращать оценку. Однако в любом случае это не является ни исполнительным, ни закрытым для изменения; он будет запрашивать таблицу N-квадратов раз для N тестов, и если вы добавите четвертый тест, этот запрос должен будет измениться, чтобы включить его в отчет.
Если комбинация Student и Test уникальна, и вы работаете в базе данных с функциональностью Pivot (чего, по-видимому, нет в SQLite), вы можете использовать сводный запрос практически с любым агрегатором (MAX/MIN/AVG/SUM набора с одним значением - это значение). В MSS2005 работает следующее:
SELECT Student, T1, T2, T3
FROM (Select Student, Test, Grade FROM ExamGrade) As SourceQuery
PIVOT (MAX(Grade) FOR Test IN (T1, T2, T3)) AS PivotTable
Это будет более впечатляюще, и это намного более элегантно. Списки столбцов по-прежнему не могут быть динамически определены AFAIK, но они тривиальны для генерации, если вы делаете этот запрос из кода приложения или используете встроенный хранимый proc sp_executesql в MS SQL Server для генерации запроса из другого хранимого proc или функция.
Ответ 5
Попробуйте это
SELECT Student, MAX(CASE WHEN Test = 'T1' THEN Grade END) AS T1,
MAX(CASE WHEN Test = 'T2' THEN Grade END) AS T2,
MAX(CASE WHEN Test = 'T3' THEN Grade END) AS T3 FROM tablename GROUP BY Student
Используйте имя таблицы вместо "tablename".