我有一个带有三个SELECT语句的SQL查询。这三个选择语句生成的数据表的图片位于www.britestudent.com/pub/1.png。三个数据表中的每一个都具有相同的列。我想将这三个表组合成一个表,以便:
(1)始终包括顶部表格(表1)中的所有行。
(2)仅当column1(UserName)和column4(CourseName)中的值与Table1中的任何行不匹配时,才包含中间表(Table2)中的行。两列都需要匹配Table2中的行才不包括在内。
(3)只有当column4(CourseName)中的值不在组合Table1和Table2的结果的任何行中时,才包含底部表(Table3)中的行。
我使用这样的SQL查询成功实现了(1)和(2):
SELECT DISTINCT
UserName AS UserName,
MAX(AmountUsed) AS AmountUsed,
MAX(AnsweredCorrectly) AS AnsweredCorrectly,
CourseName,
MAX(course_code) AS course_code,
MAX(NoOfQuestionsInCourse) AS NoOfQuestionsInCourse,
MAX(NoOfQuestionSetsInCourse) AS NoOfQuestionSetsInCourse
FROM
( "SELECT statement 1" UNION "SELECT statement 2" ) dt_derivedTable_1
GROUP BY CourseName, UserName
其中“SELECT语句1”是生成Table1的查询,“SELECT语句2”是生成Table2的查询。此查询生成的数据表的图片位于www.britestudent.com/pub/2.png。我可以使用MAX()函数,因为Table1中AmountUsed和AnsweredCorrectly列中的值将始终大于Table2中的值(并且它们在两个表的最后三列中相同)。
我失败的是实施(3)。任何有关如何做到这一点的建议将不胜感激。这很棘手,因为Table3中的UserName值为null,并且因为Table1和Table2组合结果中的CourseName值不是唯一的(但它们在表3中是唯一的)。
在实现(3)之后,最终表应该看起来像图2.png中的表,添加了表3中的最后一行(CourseName值以“4.Klasse ...”开头的行
我尝试使用SELECT,MAX()和UNION使用另一个派生表来实现(3),但我无法使其工作。下面是我的完整SQL查询,其中包含来自此失败尝试的行(3)已注释掉。
干杯, 弗雷德里克
PS - 我是这个论坛的新手(也是SQL的新手),但是通过阅读本论坛上其他人的帖子而不是阅读任何其他论坛或网站,我已经解决了以前更多的问题。这个论坛是一个很好的资源。
-- SELECT DISTINCT MAX(UserName), MAX(AmountUsed) AS AmountUsed, MAX(AnsweredCorrectly) AS AnsweredCorrectly, CourseName, MAX(course_code) AS course_code, MAX(NoOfQuestionsInCourse) AS NoOfQuestionsInCourse, MAX(NoOfQuestionSetsInCourse) AS NoOfQuestionSetsInCourse
-- FROM (
SELECT DISTINCT UserName AS UserName, MAX(AmountUsed) AS AmountUsed, MAX(AnsweredCorrectly) AS AnsweredCorrectly, CourseName, MAX(course_code) AS course_code, MAX(NoOfQuestionsInCourse) AS NoOfQuestionsInCourse, MAX(NoOfQuestionSetsInCourse) AS NoOfQuestionSetsInCourse
FROM (
-- Table 1 - All UserAccount/Course combinations that have had quizzez.
SELECT DISTINCT dbo.win_user.user_name AS UserName,
cast(dbo.GetAmountUsed(dbo.session_header.win_user_id, dbo.course.course_id, dbo.course.no_of_questionsets_in_course) as nvarchar(10)) AS AmountUsed,
Isnull(cast(dbo.GetAnswerCorrectly(dbo.session_header.win_user_id, dbo.course.course_id, dbo.question_set.no_of_questions) as nvarchar(10)),0) AS AnsweredCorrectly,
dbo.course.course_name AS CourseName,
dbo.course.course_code,
dbo.course.no_of_questions_in_course AS NoOfQuestionsInCourse,
dbo.course.no_of_questionsets_in_course AS NoOfQuestionSetsInCourse
FROM dbo.session_detail
INNER JOIN dbo.session_header ON dbo.session_detail.session_header_id = dbo.session_header.session_header_id
INNER JOIN dbo.win_user ON dbo.session_header.win_user_id = dbo.win_user.win_user_id
INNER JOIN dbo.win_user_course ON dbo.win_user_course.win_user_id = dbo.win_user.win_user_id
INNER JOIN dbo.question_set ON dbo.session_header.question_set_id = dbo.question_set.question_set_id
RIGHT OUTER JOIN dbo.course ON dbo.win_user_course.course_id = dbo.course.course_id
WHERE (dbo.session_detail.no_of_attempts = 1 OR dbo.session_detail.no_of_attempts IS NULL)
AND (dbo.session_detail.is_correct = 1 OR dbo.session_detail.is_correct IS NULL)
AND (dbo.win_user_course.is_active = 'True')
GROUP BY dbo.win_user.user_name, dbo.course.course_name, dbo.question_set.no_of_questions, dbo.course.no_of_questions_in_course,
dbo.course.no_of_questionsets_in_course, dbo.session_header.win_user_id, dbo.course.course_id, dbo.course.course_code
UNION ALL
-- Table 2 - All UserAccount/Course combinations that do or do not have quizzes but where the Course is selected for quizzes for that User Account.
SELECT dbo.win_user.user_name AS UserName,
-1 AS AmountUsed,
-1 AS AnsweredCorrectly,
dbo.course.course_name AS CourseName,
dbo.course.course_code,
dbo.course.no_of_questions_in_course AS NoOfQuestionsInCourse,
dbo.course.no_of_questionsets_in_course AS NoOfQuestionSetsInCourse
FROM dbo.win_user_course
INNER JOIN dbo.win_user ON dbo.win_user_course.win_user_id = dbo.win_user.win_user_id
RIGHT OUTER JOIN dbo.course ON dbo.win_user_course.course_id = dbo.course.course_id
WHERE (dbo.win_user_course.is_active = 'True')
GROUP BY dbo.win_user.user_name, dbo.course.course_name, dbo.course.no_of_questions_in_course,
dbo.course.no_of_questionsets_in_course, dbo.course.course_id, dbo.course.course_code
) dt_derivedTable_1
GROUP BY CourseName, UserName
-- UNION ALL
-- Table 3 - All Courses.
-- SELECT DISTINCT null AS UserName,
-- -2 AS AmountUsed,
-- -2 AS AnsweredCorrectly,
-- dbo.course.course_name AS CourseName,
-- dbo.course.course_code,
-- dbo.course.no_of_questions_in_course AS NoOfQuestionsInCourse,
-- dbo.course.no_of_questionsets_in_course AS NoOfQuestionSetsInCourse
-- FROM dbo.course
-- WHERE is_active = 'True'
-- ) dt_derivedTable_2
-- GROUP BY CourseName
-- ORDER BY CourseName
答案 0 :(得分:1)
有了这样的过滤要求(取决于先前查询的行),我建议使用表变量。
DECLARE @MyTable TABLE
(
ID int PRIMARY KEY,
Name varchar(50),
QueryNumber int
)
INSERT INTO @MyTable (ID, Name, QueryNumber)
SELECT CustomerID, CustomerName, 1
FROM Customer
WHERE Name = "Bob"
INSERT INTO @MyTable (ID, Name, QueryNumber)
SELECT CustomerID, CustomerName, 2
FROM Customer
WHERE Name = "Joe" and CustomerID not in (SELECT ID FROM @MyTable)
INSERT INTO @MyTable (ID, Name, QueryNumber)
SELECT CustomerID, CustomerName, 3
FROM Customer
WHERE CustomerID not in (SELECT ID FROM @MyTable)
SELECT *
FROM @MyTable
答案 1 :(得分:0)
这是一个Oracle风格的解决方案:
Select
*
from table1
UNION
select
*
from table2
where not exists(
select 'x'
from table1
where
table2.username = table1.username
and table2.coursename = table1.coursename
)
UNION
select
*
from table3
where
coursename not in (
Select
coursename
from table1
UNION /* the union operator implies distinct, so
there will be no duplicates */
select
coursename
from table2
where not exists(
select 'x'
from table1
where
table2.username = table1.username
and table2.coursename = table1.coursename
)
)