我正在使用Java和SQL来编写我正在编写的数据库程序(使用Oracle数据库)。假设我有一个如下表:
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?提前谢谢。
答案 0 :(得分: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
)。
“where exists”进一步将结果限制为仅包含当前主要记录的先前记录的记录。
使用样本数据:
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)
这使用相同的逻辑,但是使用内部联接和大小写何时显示所有行,并使用切回标记。
答案 1 :(得分:0)
假设您有一个名为“Key”的自动递增主键字段,我认为您可以使用自联接来获取代表切回的行:
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)