I've provided statements to create the two example tables for my question below.
In this example, the second table contains the same student id multiple times due to having multiple classIDs. However, I need the query results to be displayed horizontally on one row. (The max # of classID's per studentid is 15)
How would you write a select statement that joins the two tables and all classID data repeats within the same column like the example below:
CREATE TABLE Student (
StudentId int,
FirstName VarChar (255),
LastName VarChar (255)
);
CREATE TABLE Classes (
StudentId int,
ClassId int,
ClassName VarChar (255),
ClassCost int
);
INSERT INTO Student (StudentId, FirstName, LastName)
VALUES
(123, 'Carol', 'Dwek'),
(456, 'Cal', 'Newport');
INSERT INTO Classes (StudentId, ClassId, ClassName,ClassCost)
VALUES
(123, 972, 'Psychology',30),
(456, 214, 'Focus',99),
(123, 903, 'Sociology',30),
(456, 851, 'Meditation',99),
(456, 911, 'Reading',20),
(456, 111, 'Deep Work',50),
(456, 117, 'Time Management',25),
(456, 999, 'Goal Setting',50);
Results:
2条答案
按热度按时间zte4gxcn1#
If you are happy to use a hardcoded ceiling on number of classes a student can attend then a way that should perform better than multiple self joins (which will likely re-evaluate the row numbering multiple times) is to use the numbering to pivot on instead.
The same ordering that provides the row numbering (
StudentId, ClassId
) can also be used to do the grouping byStudentId
(provided byprimary key (StudentId, ClassId)
in the plan below)The query is still pretty ugly though and best done in the application (if there is an application and you aren't just running adhoc queries in SSMS to view the results there)
olhwl3o22#
This is only possible in a single query if you know in advance how many potential classes a student might possibly have. If you don't know and can't guess a reasonable maximum, the SQL language simply will NOT be able to produce the desired output in a single statement.
If you can guess the maximum course load, the query looks like this:
Note: this tends to be SLOW — and not just a little slow; we're talking several minutes to finish (or longer) if you have a reasonable amount of data. And, yes, you really do have to repeat yourself in two places for as many times as you have possible class enrollments.
It's also worth mentioning here this kind of
PIVOT
is antithetical to the formal set theory which underpins all relational databases. For this reason, you're usually MUCH better off doing this work in the client code or reporting tool.