Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
johnsql
Posting Yak Master
161 Posts |
Posted - 2006-08-01 : 10:00:30
|
| Knights,I have 3 tables like.table "Section"--------------companyID sectionID ClassID SectionTyID ----------- ----------- ----------- ----------- 1370 295 198 11370 300 198 21370 482 277 1table "SectionTeacher"---------------------companyID sectionID userID ----------- ----------- ----------- 1370 295 1890221370 295 2015831370 295 2418601370 300 2015831370 300 2422311370 482 241860table "users"-------------companyID userID firstName lastName ----------- ----------- -------------------------------------------------- -------------------------------------------------- 1370 189022 Cardin Henson1370 201583 Dean Dusentoff1370 241860 Kim Adams1370 242231 June CleaverNow I want to combine the 3 tables in a query such that the result gives me combined teachers name for each sectionID in 1 line. But I do not want to use loop or cursor because they increase the running time. Do you have any ideas to do so? The results I want looks like (One sectionID may have more than 1 teacher being assigned to it).companyID SectionID ClassID SectionTyID Teachers----------- ---------- ------- ----------- ---------------------------------------------1370 295 198 1 Cardin Henson, Dean Dusentoff, Kim Adams1370 300 198 2 Dean Dusentoff, June Cleaver1370 482 277 1 Kim AdamsThanks very much in advance for any ideas. |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-08-01 : 10:07:36
|
| You can do without loop, but that is awkward and not pretty.And besides, looping is very fast when implemented the right way.Peter LarssonHelsingborg, Sweden |
 |
|
|
Srinika
Master Smack Fu Yak Hacker
1378 Posts |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-08-01 : 10:24:59
|
| [code]-- prepare test datadeclare @section table (companyid int, sectionid int, classid int, sectiontyid int)insert @sectionselect 1370, 295, 198, 1 union allselect 1370, 300, 198, 2 union allselect 1370, 482, 277, 1declare @sectionteacher table (companyid int, sectionid int, userid int)insert @sectionteacherselect 1370, 295, 189022 union allselect 1370, 295, 201583 union allselect 1370, 295, 241860 union allselect 1370, 300, 201583 union allselect 1370, 300, 242231 union allselect 1370, 482, 241860declare @users table (companyid int, userid int, firstName varchar(100), lastName varchar(100))insert @usersselect 1370, 189022, 'Cardin', 'Henson' union allselect 1370, 201583, 'Dean', 'Dusentoff' union allselect 1370, 241860, 'Kim', 'Adams' union allselect 1370, 242231, 'June', 'Cleaver'-- Stage the dataDECLARE @Stage TABLE ( CompanyID INT, SectionID INT, ClassID INT, SectionTypeID INT, Teacher VARCHAR(200) )INSERT @StageSELECT s.companyid, s.sectionid, s.classid, s.sectiontyid, u.firstName + ' ' + u.lastNameFROM @section sINNER JOIN @sectionteacher st ON st.companyid = s.companyid AND st.sectionid = s.sectionidINNER JOIN @users u ON u.companyid = st.companyid AND u.userid = st.userid-- Do the actual workDECLARE @Output TABLE ( RowID INT IDENTITY(0, 1) Primary KEY CLUSTERED, CompanyID INT, SectionID INT, ClassID INT, SectionTypeID INT, Teachers VARCHAR(8000) )INSERT @Output ( CompanyID, SectionID, ClassID, SectionTypeID )SELECT DISTINCT CompanyID, SectionID, ClassID, SectionTypeIDFROM @StageORDER BY CompanyID, SectionID, ClassID, SectionTypeIDDECLARE @RowID INT, @Teachers VARCHAR(8000), @CompanyID INT, @SectionID INT, @ClassID INT, @SectionTypeID INTSELECT @RowID = MAX(RowID), @Teachers = ''FROM @OutputWHILE @RowID >= 0 BEGIN SELECT @CompanyID = CompanyID, @SectionID = SectionID, @ClassID = ClassID, @SectionTypeID = SectionTypeID FROM @Output WHERE RowID = @RowID SELECT @Teachers = LEFT(@Teachers + CASE WHEN @Teachers = '' THEN '' ELSE ', ' END + z.Teacher, 8000) FROM ( SELECT TOP 100 PERCENT Teacher FROM @Stage WHERE CompanyID = @CompanyID AND SectionID = @SectionID AND ClassID = @ClassID AND SectionTypeID = @SectionTypeID ORDER BY Teacher ) z UPDATE @Output SET Teachers = @Teachers WHERE RowID = @RowID SELECT @RowID = @RowID - 1, @Teachers = '' END-- Show the outputSELECT CompanyID, SectionID, ClassID, SectionTypeID, TeachersFROM @OutputORDER BY RowID[/code]Peter LarssonHelsingborg, Sweden |
 |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
Posted - 2006-08-01 : 11:04:00
|
| Note that if concatenated strings exceeds the length of 8000, you may need to use more than one variableMadhivananFailing to plan is Planning to fail |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-08-01 : 12:58:50
|
| The user-defined function method described in the link provided is by far the shortest, fastest and easiest way to do this. No loops needed, no cursors.- Jeff |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-08-01 : 13:43:21
|
| The function does exactly the same thing as my "SELECT @Teachers..." statement.Comparing a SELECT DISTINCT ... , dbo.fnConcat and the while loop above, is the same, exept for one thing, I do not have the overhead of calling a function.Peter LarssonHelsingborg, Sweden |
 |
|
|
johnsql
Posting Yak Master
161 Posts |
Posted - 2006-08-01 : 13:43:38
|
| Madhivanan You said "Note that if concatenated strings exceeds the length of 8000, you may need to use more than one variable". So, how can I do that? Thanks. |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-08-01 : 13:47:24
|
quote: Originally posted by Peso The function does exactly the same thing as my "SELECT @Teachers..." statement.Comparing a SELECT DISTINCT ... , dbo.fnConcat and the while loop above, is the same, exept for one thing, I do not have the overhead of calling a function.Peter LarssonHelsingborg, Sweden
You have the overhead of table variables, while loops, and UPDATE statements.Generally, the shortest technique (if not less efficient) is the way to go. the UDF is very concise and very clear.- Jeff |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-08-01 : 14:45:18
|
quote: Originally posted by johnsql Madhivanan You said "Note that if concatenated strings exceeds the length of 8000, you may need to use more than one variable". So, how can I do that? Thanks.
If a teacher's name is about 20 characters long, you can have up to about 300 teachers per company, section, class and sectiontype.Peter LarssonHelsingborg, Sweden |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-08-01 : 14:48:07
|
quote: Originally posted by jsmith8858 You have the overhead of table variables, while loops, and UPDATE statements.Generally, the shortest technique (if not less efficient) is the way to go. the UDF is very concise and very clear.
1. The function itself is a varchar that needs to be created for every row before distinct. Then distinct is applied over all columns, included the "functiongenerated" column. I create the table variable once.2. Yes, I have a while loop, one for each distinct row. But that's also what the DISTINCT statement does, after going through all records (including the teachers column) in order to decide what is distinct.3. The only different is the update statement, you are absolutely right about that.I also agree with you that a function is a more elegant solution.Peter LarssonHelsingborg, Sweden |
 |
|
|
|
|
|
|
|