Pivot?Случай?Я не уверен, как поступить - PullRequest
0 голосов
/ 30 января 2019

Использование Oracle DB.Я пытаюсь взять данные в одном столбце (ts.name) и сделать эти данные именами столбцов и сделать данные в другом столбце (sts.numscore) данными для столбца (ts.name).Я использую операторы CASE, но это не работает.Операторы CASE выставляют по одному тесту на строку.Мне нужны все результаты тестов в одном ряду.Любая помощь будет принята с благодарностью.Спасибо

SELECT schools.name AS School,
  s.lastfirst AS Student,
  s.student_number,
  s.grade_level,
  t.name AS Test_Name,
  (case when ts.name = 'ACT_Reading' then sts.numscore end) as ACT_Reading,
  (case when ts.name = 'ACT_Math' then sts.numscore end) as ACT_Math,
  (case when ts.name = 'ACT_English' then sts.numscore end) as ACT_English,
  (case when ts.name = 'ACT_Science' then sts.numscore end) as ACT_Science,
  (case when ts.name = 'ACT_Composite' then sts.numscore end) as ACT_Composite,
  to_char (st.test_date),
  sts.numscore AS Score 
FROM students s,studenttestscore sts,studenttest st,test t,testscore ts,schools
WHERE s.id = sts.studentid
AND sts.studenttestid = st.id
AND sts.testscoreid = ts.id
AND ts.testid = t.id
AND s.schoolid = schools.school_number
AND t.name = 'ACT'
AND sts.numscore > 0 
and s.enroll_status=0
AND s.schoolid=10
ORDER BY s.lastfirst,st.test_date DESC

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Чтобы получить результаты в одной строке, вам нужно объединить результаты выражений падежа;что-то вроде:

SELECT schools.name AS School,
  s.lastfirst AS Student,
  s.student_number,
  s.grade_level,
  t.name AS Test_Name,
  max(case when ts.name = 'ACT_Reading' then sts.numscore end) as ACT_Reading,
  max(case when ts.name = 'ACT_Math' then sts.numscore end) as ACT_Math,
  max(case when ts.name = 'ACT_English' then sts.numscore end) as ACT_English,
  max(case when ts.name = 'ACT_Science' then sts.numscore end) as ACT_Science,
  max(case when ts.name = 'ACT_Composite' then sts.numscore end) as ACT_Composite,
  to_char (st.test_date)
FROM students s,studenttestscore sts,studenttest st,test t,testscore ts,schools
WHERE s.id = sts.studentid
AND sts.studenttestid = st.id
AND sts.testscoreid = ts.id
AND ts.testid = t.id
AND s.schoolid = schools.school_number
AND t.name = 'ACT'
AND sts.numscore > 0 
and s.enroll_status=0
AND s.schoolid=10
GROUP BY schools.name,
  s.lastfirst,
  s.student_number,
  s.grade_level,
  t.name,
  st.test_date
ORDER BY s.lastfirst, st.test_date DESC

Поскольку вы эффективно поворачиваете счет, вы не хотите включать его в качестве своего собственного столбца, в список выбора или в группу.

Было бы лучше использовать современный синтаксис объединения вместо древнего списка таблиц, разделенных запятыми в предложении from;и вы должны также предоставить модель формата в вызове to_char() для даты:

SELECT schools.name AS school,
  s.lastfirst AS student,
  s.student_number,
  s.grade_level,
  t.name AS test_name,
  MAX(CASE WHEN ts.NAME = 'ACT_Reading' THEN sts.numscore END) AS act_reading,
  MAX(CASE WHEN ts.NAME = 'ACT_Math' THEN sts.numscore END) AS act_math,
  MAX(CASE WHEN ts.NAME = 'ACT_English' THEN sts.numscore END) AS act_english,
  MAX(CASE WHEN ts.NAME = 'ACT_Science' THEN sts.numscore END) AS act_science,
  MAX(CASE WHEN ts.NAME = 'ACT_Composite' THEN sts.numscore END) AS act_composite,
  to_char(st.test_date, 'YYYY-MM-DD') AS test_date
FROM students s
JOIN studenttestscore sts ON s.id = sts.studentid
JOIN studenttest st ON sts.studenttestid = st.id
JOIN testscore ts ON sts.testscoreid = ts.id
JOIN test t ON ts.testid = t.id
JOIN schools ON s.schoolid = schools.school_number
WHERE t.name = 'ACT'
AND sts.numscore > 0 
and s.enroll_status=0
AND s.schoolid=10
GROUP BY schools.name,
  s.lastfirst,
  s.student_number,
  s.grade_level,
  t.name,
  st.test_date
ORDER BY s.lastfirst, st.test_date DESC

Эквивалент с использованием pivot будет выглядеть примерно так:

SELECT school, student, student_number, grade_level, test_name,
  act_reading, act_math, act_english, act_science, act_composite,
  to_char(test_date, 'YYYY-MM-DD') AS test_date
FROM (
  SELECT schools.name AS school,
    s.lastfirst AS student,
    s.student_number,
    s.grade_level,
    t.name AS test_name,
    ts.name AS test_score_name,
    sts.numscore,
    st.test_date
  FROM students s
  JOIN studenttestscore sts ON s.id = sts.studentid
  JOIN studenttest st ON sts.studenttestid = st.id
  JOIN testscore ts ON sts.testscoreid = ts.id
  JOIN test t ON ts.testid = t.id
  JOIN schools ON s.schoolid = schools.school_number
  WHERE t.name = 'ACT'
  AND sts.numscore > 0 
  AND s.enroll_status=0
  AND s.schoolid=10
)
PIVOT (
  max(numscore)
  FOR test_score_name IN (
    'ACT_Reading' AS act_reading,
    'ACT_Math' AS act_math,
    'ACT_English' AS act_english,
    'ACT_Science' AS act_science,
    'ACT_Composite' AS act_composite
  )
) p
ORDER BY p.student, p.test_date DESC

, но это будетв любом случае переведите его в агрегатную / падежную версию.

(Конечно, все не проверено, поскольку у нас нет вашей схемы для игры ...)

0 голосов
/ 30 января 2019

Вы на правильном пути, и вы пытаетесь написать сводный запрос.Вот исправленная версия.Требуется max каждого выражения CASE, чтобы получить желаемое значение в одной строке.Кроме того, он использует правильные явные соединения между всеми таблицами.Это предпочтительный способ написания современного SQL-запроса.

SELECT
    sc.name AS School,
    s.lastfirst AS Student,
    s.student_number,
    s.grade_level,
    t.name AS Test_Name,
    MAX(CASE WHEN ts.name = 'ACT_Reading'   THEN sts.numscore end) AS ACT_Reading,
    MAX(CASE WHEN ts.name = 'ACT_Math'      THEN sts.numscore end) AS ACT_Math,
    MAX(CASE WHEN ts.name = 'ACT_English'   THEN sts.numscore end) AS ACT_English,
    MAX(CASE WHEN ts.name = 'ACT_Science'   THEN sts.numscore end) AS ACT_Science,
    MAX(CASE WHEN ts.name = 'ACT_Composite' THEN sts.numscore end) AS ACT_Composite,
    TO_CHAR(st.test_date),
    sts.numscore AS Score
FROM students s
INNER JOIN studenttestscore sts
    ON s.id = sts.studentid
INNER JOIN studenttest st
    ON sts.studenttestid = st.id
INNER JOIN test score ts
    ON sts.testscoreid = ts.id
INNER JOIN test t
    ON ts.testid = t.id
INNER JOIN schools sc
    ON s.schoolid = sc.school_number
WHERE
    t.name = 'ACT' AND
    sts.numscore > 0 AND
    s.enroll_status = 0 AND
    s.schoolid = 10
GROUP BY
    sc.name,
    s.lastfirst,
    s.student_number,
    s.grade_level,
    t.name,
    st.test_date,
    sts.numscore
ORDER BY
    s.lastfirst,
    st.test_date DESC;
0 голосов
/ 30 января 2019

Вам нужно использовать условную агрегацию, как показано ниже -

SELECT schools.name AS School,
  s.lastfirst AS Student,
  s.student_number,
  s.grade_level,
  t.name AS Test_Name,
  max(case when ts.name = 'ACT_Reading' then sts.numscore end) as ACT_Reading,
  max(case when ts.name = 'ACT_Math' then sts.numscore end) as ACT_Math,
  max(case when ts.name = 'ACT_English' then sts.numscore end) as ACT_English,
  max(case when ts.name = 'ACT_Science' then sts.numscore end) as ACT_Science,
  max(case when ts.name = 'ACT_Composite' then sts.numscore end) as ACT_Composite,
  to_char (st.test_date),
  sts.numscore AS Score 
FROM students s join studenttestscore sts on s.id = sts.studentid
join studenttest st on sts.studenttestid = st.id
join test t on sts.testscoreid = ts.id
join testscore ts on ts.testid = t.id
join schools on s.schoolid = schools.school_number
WHERE t.name = 'ACT' AND sts.numscore > 0 
and s.enroll_status=0 AND s.schoolid=10
group by schools.name,
  s.lastfirst ,
  s.student_number,
  s.grade_level,
  t.name, to_char (st.test_date),sts.numscore
ORDER BY s.lastfirst,st.test_date DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...