比方说,我有两张桌子:
Student_ID
,Class_ID
Class_ID
,Attribute_ID
和其他字段[底部的示例数据]
要求:
没有条件#2和#3,这是一个简单的INNER JOIN
SELECT sc.student_id, c.*
FROM Student_class sc
JOIN Class c ON sc.class_id=c.class_id
WHERE c.attribute_id = ... AND sc.student_id IN (...)
如果没有#3,那就是OUTER JOIN
SELECT sc.student_id, c.*
FROM Student_class sc
LEFT JOIN Class c ON sc.class_id=c.class_id AND c.attribute_id = ...
WHERE sc.student_id IN (...)
满足所有这三个要求 - 我正在努力。
SELECT DISTINCT sc.student_id, c.*
FROM Student_class sc
LEFT JOIN Class c ON sc.class_id=c.class_id AND c.attribute_id = ...
WHERE sc.student_id IN (...)
无论是否找到具有该属性的类,上面都会生成 NULL行。
我在考虑为列表中的每个学生动态创建NULL row
,并UNION
将其与INNER JOIN
结果一起动态创建。
SELECT student_id, NULL, NULL, ... , ...
UNION
SELECT sc.student_id, c.*
FROM Student_class sc
JOIN Class c ON sc.class_id=c.class_id
WHERE c.attribute_id = ... AND sc.student_id IN (...)
以上内容在第一个查询中需要正确数量的NULL,因此无法承受更改表格。
我错过了一些明显的东西吗?
示例数据:
Student_Class:
Student_ID Class_ID
0001 0050
0001 0150
0002 0050
0002 0100
0002 0155
0002 1200
0002 1155
0003 1155
0004 0050
0004 0155
类别:
Class_ID Attribute_ID Value1 Value2 Value3
0050 A1 1 2 3
0100 A2 4 5 6
0150 A3 7 8 9
0155 A1 9 8 7
1155 A4 6 5 4
1200 A4 3 2 1
Student ID
的所需结果:0001,0002,0003和Attribute_ID
:A1。
Student_Id Class_ID Attribute_ID Value1 Value2 Value3
0001 050 A1 1 2 3
0002 050 A1 1 2 3
0002 155 A1 9 8 7
0003 NULL NULL NULL NULL NULL
答案 0 :(得分:1)
使用CTE和分区功能(ROW_NUMBER())
可以轻松实现DECLARE @Student_Class TABLE (Student_ID varchar(10), Class_ID varchar(10));
INSERT INTO @Student_Class VALUES('0001', '0050');
INSERT INTO @Student_Class VALUES('0001', '0150');
INSERT INTO @Student_Class VALUES('0002', '0050');
INSERT INTO @Student_Class VALUES('0002', '0100');
INSERT INTO @Student_Class VALUES('0002', '0155');
INSERT INTO @Student_Class VALUES('0002', '1200');
INSERT INTO @Student_Class VALUES('0002', '1155');
INSERT INTO @Student_Class VALUES('0003', '1155');
INSERT INTO @Student_Class VALUES('0004', '0050');
INSERT INTO @Student_Class VALUES('0004', '0155');
DECLARE @Class TABLE (Class_ID varchar(10), Attribute_ID varchar(10), Value1 int);
INSERT INTO @Class VALUES('0050', 'A1', 1);
INSERT INTO @Class VALUES('0100', 'A2', 4);
INSERT INTO @Class VALUES('0150', 'A3', 7);
INSERT INTO @Class VALUES('0155', 'A1', 9);
INSERT INTO @Class VALUES('1155', 'A4', 6);
INSERT INTO @Class VALUES('1200', 'A4', 3);
WITH TempData_CTE (Student_ID, Class_ID, Attribute_ID, Value1, rowNum)
AS
(
SELECT sc.Student_ID,
c.Class_ID,
c.Attribute_ID,
c.Value1,
ROW_NUMBER() OVER (PARTITION BY sc.Student_ID ORDER BY sc.Student_ID DESC) AS rowNum
FROM @Student_Class sc
LEFT JOIN @Class c ON sc.class_id = c.class_id AND c.Attribute_ID = 'A1'
WHERE sc.Student_ID IN (0001, 0002, 0003)
)
SELECT Student_ID, Class_ID, Attribute_ID, Value1
FROM TempData_CTE
WHERE Class_ID IS NOT NULL OR rowNum = 1
答案 1 :(得分:0)
我认为你的left join
应该可以正常工作:
SELECT sc.student_id, c.*
FROM Student_class sc LEFT JOIN
Class c
ON sc.class_id = c.class_id AND c.attribute_id = ...
WHERE sc.student_id IN (...);
如果没有匹配,那么每个学生和每个不匹配的班级只会得到一行。如果学生可以有多个不匹配的课程,您可以这样做:
SELECT DISTINCT sc.student_id, c.*
FROM Student_class sc LEFT JOIN
Class c
ON sc.class_id = c.class_id AND c.attribute_id = ...
WHERE sc.student_id IN (...);
但是,我个人会在每个非匹配类中一行,并且我在查询中包含该类:
SELECT sc.student_id, sc.class_id, c.*
FROM Student_class sc LEFT JOIN
Class c
ON sc.class_id = c.class_id AND c.attribute_id = ...
WHERE sc.student_id IN (...);
答案 2 :(得分:0)
您将必须运行一个连接两个子查询结果的查询:
获取所有具有匹配课程的学生ID列表(但不一定是所有学生ID)。
SELECT
Student_Class.Student_Id,
Student_Class.Class_Id
from
Student_Class
INNER JOIN
Class
ON Student_Class.Class_Id = Class.Class_Id
WHERE
Class.Attribute_ID = @Attribute_ID
我们还需要一份所有学生的清单。这个数据库几乎肯定有一个学生表,但是为了这个练习,我们假装它没有。我们将通过此查询获取学生ID列表:
SELECT DISTINCT Student_Class.Student_ID from Student_Class
现在我们将这两个查询结合起来
SELECT
Students.ID,
Matching_Classes.Class_ID
FROM
(
SELECT DISTINCT
Student_Class.Student_ID
from
Student_Class
)
Students
LEFT OUTER JOIN
(
SELECT
Student_Class.Student_Id,
Student_Class.Class_Id
FROM
Student_Class
INNER JOIN
Class
on Student_Class.Class_Id = Class.Class_Id
WHERE
Class.Attribute_ID = @Attribute_ID
)
Matching_Classes
ON Students.Student_Id = Matching_Classes.Student_Id
WHERE Students.ID IN (...)