ORACLE SQL с моим полу-начинающим опытом.
У меня есть таблица Credits
по одной строке на идентификатор:
ID, ArtCred, BizCred, HumCred, NatCred, TekCred, GenCred
5001, 12, 7.5, 12, 14, 11, 9
5002, 10.5, 6, 5, 4, 6, 3
с идентификатором для каждого студента и кредитами для каждой группы курса.
Учащиеся могут выбрать группу (группы) курса, на которой они сосредоточатся, из таблицы GrpChoice, в которой указан их выбор и дата, когда они его сделали.
ID, GroupChoice, DateChoice
5001, ART, 3/3/2010
5001, BIZ, 5/5/2015
5001, NAT, 6/23/2022
5002, ART, 6/23/2023
Я могу запросить кредиты каждой группы для каждого студента, даже если он не выбран):
SELECT
ID,
GroupChoice,
artcred,
bizcred,
humcred,
natcred,
tekcred,
gencred
FROM
Grpchoice
INNER JOIN
Credits ON GrpChoice.ID = Credits.ID
ORDER BY
Grpchoice.datechoice Desc
ID Group Art Biz Hum Nat Tek Gen
5001 TEK 12 7.5 12 14 11 9
5001 HHS 12 7.5 12 14 11 9
5001 BIZ 12 7.5 12 14 11 9
5001 ART 12 7.5 12 14 11 9
5002 ART 10.5 6 5 4 6 3
но мне нужно показать для каждого идентификатора и кредитов, полученных для GrpChoice (отсортировать по дате desc):
Я хочу видеть только для ID 5001:
ART 12
BIZ 7.5
NAT 14
Для идентификатора 5002:
ART 10.5
Я пробовал PIVOT, но, поскольку значение GrpChoice может измениться, я не думаю, что смогу его использовать. Если я не настрою свои данные по-другому для поворота по идентификатору... Я только читал о поворотах.
CASE GRPCHOICE не будет работать, потому что он не изменит SELECT на основе его значения (я не могу «SELECT CASE When GrpChoice = "Art", затем SELECT artCHr, WHEN GrpChoice="BIZ", затем SELECT bizCHr...") .
Я просмотрел OVER (PARTITION BY), но не понимаю, как это будет работать.
Предложения приветствуются, спасибо.
В своем ответе MT0 показывает, как преобразовать таблицу кредитов на лету. Но было бы лучше изменить таблицу в базе данных, чтобы запрос не должен был знать, какие субъекты существуют в базе данных.
Есть два набора данных. Выбор группы - это имя группы в качестве данных. Затем кредиты, полученные для каждой группы, представляют собой данные с именем группы в качестве имени субъекта / поля. Группы постоянны, и каждая группа имеет кредитное значение. Но выбор может меняться и иметь несколько значений с течением времени.
Используйте UNPIVOT
вместо PIVOT
, а затем соедините две таблицы:
SELECT c.id, subject, credit
FROM credits
UNPIVOT (
credit FOR subject IN (
artcred As 'ART',
bizcred AS 'BIZ',
humcred AS 'HUM',
natcred AS 'NAT',
tekcred AS 'TEK',
gencred AS 'GEN'
)
) c
INNER JOIN grpchoice g
ON c.id = g.id AND c.subject = g.groupchoice
Что для примера данных:
CREATE TABLE credits (ID, ArtCred, BizCred, HumCred, NatCred, TekCred, GenCred) AS
SELECT 5001, 12, 7.5, 12, 14, 11, 9 FROM DUAL UNION ALL
SELECT 5002, 10.5, 6, 5, 4, 6, 3 FROM DUAL;
CREATE TABLE GrpChoice (ID, GroupChoice, DateChoice) AS
SELECT 5001, 'ART', DATE '2010-03-03' FROM DUAL UNION ALL
SELECT 5001, 'BIZ', DATE '2015-05-05' FROM DUAL UNION ALL
SELECT 5001, 'NAT', DATE '2022-06-23' FROM DUAL UNION ALL
SELECT 5002, 'ART', DATE '2023-06-23' FROM DUAL;
Выходы:
Интересный. Я бы никогда не догадался, что существует заявление UNPIVOT. Такой результат выглядит идеально.
На самом деле, с предоставленными образцами данных вы можете использовать выражение CASE для получения ожидаемого результата:
WITH -- Sample Data
credits AS
(
Select 5001 "ID", 12 "ARTCRED", 7.5 "BIZCRED", 12 "HUMCRED", 14 "NATCRED", 11 "TEKCRED", 9 "GENCRED" From Dual Union All
Select 5002 "ID", 10.5 "ARTCRED", 6 "BIZCRED", 5 "HUMCRED", 4 "NATCRED", 6 "TEKCRED", 3 "GENCRED" From Dual
),
grp_choices AS
(
Select 5001 "ID", 'ART' "GROUPCHOICE", To_Date('03.03.2010', 'dd.mm.yyyy') "DATECHOICE" From Dual Union All
Select 5001 "ID", 'BIZ' "GROUPCHOICE", To_Date('05.05.2015', 'dd.mm.yyyy') "DATECHOICE" From Dual Union All
Select 5001 "ID", 'NAT' "GROUPCHOICE", To_Date('23.06.2022', 'dd.mm.yyyy') "DATECHOICE" From Dual Union All
Select 5002 "ID", 'ART' "GROUPCHOICE", To_Date('23.06.2023', 'dd.mm.yyyy') "DATECHOICE" From Dual
)
--
-- M a i n S Q L
Select c.ID,
g.GROUPCHOICE,
CASE g.GROUPCHOICE
WHEN 'ART' THEN c.ARTCRED
WHEN 'BIZ' THEN c.BIZCRED
WHEN 'HUM' THEN c.HUMCRED
WHEN 'NAT' THEN c.NATCRED
WHEN 'TEK' THEN c.TEKCRED
WHEN 'GEN' THEN c.GENCRED
ELSE 0
END "CREDIT"
From credits c
Inner Join grp_choices g ON(g.ID = c.ID)
--
-- R e s u l t :
ID GROUP CREDIT
---------- ----- ----------
5001 ART 12
5001 BIZ 7.5
5001 NAT 14
5002 ART 10.5
Вот почему я спросил. Я знал, что должен быть простой способ расколоть этот орех. Спасибо.
Проблема в дизайне базы данных. В таблице GrpChoice ART, BIZ, NAT и т.д. есть данные. В таблице Credits есть структура (ArtCred, BizCred и т.д.). Решите, должны ли эти темы быть частью структуры базы данных или просто данными в базе данных. Не смешивайте это. Я предлагаю сделать темы данными, чтобы вы могли легко добавить тему или удалить тему в любое время. Это означает, что вы должны изменить таблицу Credits, чтобы она имела три столбца: идентификатор студента, предмет и кредит.