2013-07-10 6 views
1

Я использую как Java, так и SQL для программы базы данных, которую я пишу (используя Oracle Database). Предположим, у меня есть таблица вроде следующего:Создание столбца в базе данных на основе сравнения нескольких столбцов

Student   Major 

Student1  CS 
Student1  Math 
Student1  CS 
Student2  English 
Student2  Bio 
Student2  English 

Что такое лучший способ, который я могу экземпляры флаг, где студент изменился с одного майора к другому и вернулся к своим первоначальным основным? В идеале, результат будет выглядеть следующим образом:

Student   Major   Flagged_Values 

Student1  CS 
Student1  Math 
Student1  CS     1 
Student2  English 
Student2  CS 
Student2  English   1 

С Student1 и Student2 изменились майоры, а затем вернулся к оригиналу. Я новичок в программировании базы данных, а часть, с которой я запутался, сравнивает значения из нескольких столбцов на основе студента или номера идентификатора, такого как мой пример выше. Если кто-нибудь может объяснить, как это сделать, это было бы полезно.

String switches = "SELECT Table.Student, Table.Major, " + 
      "COUNT(*)OVER (partition by Major)WHERE(partition by Student)" + 
      "AS Switches FROM Table"; 
    ResultSet result = st.executeQuery(switches); 

Вот код, который я до этого момента, но я не знаю, если разделяющей два раза в одном операторе будет работать, или если потребуется подсекции. Если бы я хотел добавить новый столбец со значениями, отмеченными значком, мне нужен цикл while для повторения через ResultSet выше? Заранее спасибо.

ответ

1

Во-первых, вам нужно поле, чтобы определить порядок этих изменений. В противном случае не может быть понятия «предыдущий». В моем примере ниже я использую поле «trans», которое увеличивается с каждым изменением ученика.

Я бы использовал два подзапроса - один для захвата непосредственно предшествующей транзакции (чтобы определить, является ли эта транзакция основным коммутатором), и один, чтобы определить, применим ли текущий майор в любой предыдущей транзакции.

Я сделал это двумя способами. Первый отображает только те записи, которые удовлетворяют критериям, и это показывает текущий крупный и самый последний из основных:

select 
    students.student, 
    students.major, 
    students.trans, 
    prev_row.major prev_major, 
    prev_row.trans prev_trans 
from 
    students 
    join students prev_row 
    on (students.student = prev_row.student 
     and students.trans = prev_row.trans + 1 
     and students.major != prev_row.major) 
where 
    exists (select 'x' 
      from students prev_row 
      where students.student = prev_row.student 
       and students.trans > prev_row.trans + 1 
       and students.major = prev_row.major); 

второй таблице в соединении («prev_row») находит предшествующая строка студента (students.trans = prev_row.trans + 1), но только если майор отличается (students.major != prev_row.major).

«Где существует» далее ограничивает результат только теми записями, где существует предыдущая запись с текущим майором.

Использование выборки данных:

Student  Maj. Trans 
Student1 CS  1 
Student1 Math 2 
Student1 CS  3 
Student2 English 1 
Student2 Math 2 
Student2 Math 3 
Student2 Math 4 
Student2 English 5 
Student2 Law  6 
Student2 Math 6 

Это даст следующий результат:

STUDENT  MAJOR TRANS PREV_MAJOR PREV_TRANS 
Student1 CS  3  Math   2 
Student2 English 5  Math   4 
Student2 Math 6  English   5 

Второй подход я использовал будет отображать желаемый результат:

select 
    students.student, 
    students.major, 
    students.trans, 
    case when prev_row.student is not null 
      and exists (select 'x' 
          from students prev_row 
          where students.student = prev_row.student 
           and students.trans > prev_row.trans + 1 
           and students.major = prev_row.major) 
     then 1 else null end is_back 
from 
    students 
    left join students prev_row 
    on (students.student = prev_row.student 
     and students.trans = prev_row.trans + 1 
     and students.major != prev_row.major) 

При этом используется та же логика, но вместо этого использует внутреннее соединение и случай, когда отображать все строки, и отмечать те, что w с отключением.

SQLFiddle here

+0

Спасибо, Джо. Это очень полезно! Я ценю это. – user2554121

0

Предполагая, что у вас есть поле первичного ключа автоинкрементного под названием «Ключ», я думаю, что вы можете использовать автообъединение, чтобы получить строки, которые представляют собой переключатель обратно:

SELECT s1.Key 
FROM [student_table] s1 
JOIN [student_table] s2 on s1.Student = s2.Student AND s1.Major = s2.Major 
WHERE s1.Key > s2.Key 

Убедитесь, что работы для ваших данных. Тогда для выполнения фактического обновления ... не это должно быть так же просто, как добавление Flagged_Values столбец, а затем, выполнив запрос:

UPDATE [student_table] s 
SET s.Flagged_Values = 1 
WHERE s.Key IN 
    (SELECT s1.Key 
    FROM [student_table] s1 
    JOIN [student_table] s2 on s1.Student = s2.Student AND s1.Major = s2.Major 
    WHERE s1.Key > s2.Key) 
+0

Благодарим за помощь Джеффри! – user2554121

Смежные вопросы