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 |
R
Constraint Violating Yak Guru
328 Posts |
Posted - 2010-11-04 : 12:35:19
|
I have three tables; one is a table variable, and the other two are many-to-many tables. My query always searches @tmp, but I was wondering if it is possible to only query the other two tables when a variable is passed to query them with. Here's what I'm doing so far which should hopefully explain what I mean... -- if no parameter values passed, then only query table variable IF @performanceCriteriaID IS NULL AND @businessObjectiveID IS NULL BEGIN -- search all user answers without querying many-to-many tables SELECT * FROM @tmp ORDER BY surname, name END -- otherwise, query the many-to-many tables using the passed variables ELSE BEGIN -- query many-to-many table(s) SELECT DISTINCT(tmp.answerID), tmp.* FROM @tmp tmp LEFT OUTER JOIN [tbl_BusinessObjectives] bo ON bo.uiAnswerID = tmp.answerID LEFT OUTER JOIN -- only when needed? [tbl_PerformanceCriteria] pc ON pc.uiAnswerID = tmp.answerID -- only when needed? WHERE (bo.boID = @businessObjectiveID OR @businessObjectiveID IS NULL) AND (pc.pcID = @performanceCriteriaID OR @performanceCriteriaID IS NULL) ORDER BY tmp.surname, tmp.name END So here's the pseudo code I'm aiming for...1. If @performanceCriteriaID and @businessObjectiveID are null, just query @tmp2. If @performanceCriteriaID is not null, return rows from @tmp where a related row(s) exists in [tbl_BusinessObjectives]3. If @businessObjectiveID is not null, return rows from @tmp where a related row(s) exists in [tbl_PerformanceCriteria]4. If 2+3 are both not null, return rows from @tmp where a related row(s) exists in [tbl_BusinessObjectives] and [tbl_PerformanceCriteria]So I guess I'm trying to join only when required. I only return row values from @tmp to prevent duplicate @tmp rows showing when multiple related rows exist in the other table(s). Or am I wasting my time?!?  |
|
mikgri
Starting Member
39 Posts |
Posted - 2010-11-09 : 10:53:36
|
Instead using left joins, use union and inner join with each table with proper criteria. |
 |
|
R
Constraint Violating Yak Guru
328 Posts |
Posted - 2010-11-09 : 11:02:39
|
Can you give an example please? |
 |
|
webfred
Master Smack Fu Yak Hacker
8781 Posts |
Posted - 2010-11-09 : 11:18:18
|
Better you would give table structure of- @tmp (and maybe how the data is coming into @tmp)- tbl_BusinessObjectives- tbl_PerformanceCriteriaand some sample data for each tableand the wanted result set(s) in relation to sample data and in relation to the parameter values. No, you're never too old to Yak'n'Roll if you're too young to die. |
 |
|
mikgri
Starting Member
39 Posts |
Posted - 2010-11-09 : 11:46:10
|
You can use some thing like this: IF @performanceCriteriaID IS NULL AND @businessObjectiveID IS NULL BEGIN -- search all user answers without querying many-to-many tables SELECT * FROM @tmp ORDER BY surname, name END -- otherwise, query the many-to-many tables using the passed variables ELSE BEGIN -- query many-to-many table(s) SELECT DISTINCT(tmp.answerID), tmp.* FROM @tmp tmp INNER JOIN [tbl_BusinessObjectives] bo ON bo.uiAnswerID = tmp.answerID and bo.boID = ISNULL(@businessObjectiveID,0) UNION SELECT DISTINCT(tmp.answerID), tmp.* FROM @tmp tmp INNER JOIN [tbl_PerformanceCriteria] pc ON pc.uiAnswerID = tmp.answerID AND pc.pcID = ISNULL(@performanceCriteriaID,0) END |
 |
|
mikgri
Starting Member
39 Posts |
Posted - 2010-11-09 : 12:26:16
|
instead bo.boID = ISNULL(@businessObjectiveID,0)you can use bo.boID = @businessObjectiveIDwhere isnull(@businessObjectiveID,0)>0depend on structure of your tables. |
 |
|
R
Constraint Violating Yak Guru
328 Posts |
Posted - 2010-11-09 : 12:35:34
|
mikgriSo are you saying the syntax would be...INNER JOIN [tbl_BusinessObjectives] bo ON bo.uiAnswerID = tmp.answerID and bo.boID = @businessObjectiveIDwhere isnull(@businessObjectiveID, 0) > 0 I didn't know you could JOIN and specify WHERE on that JOIN... |
 |
|
mikgri
Starting Member
39 Posts |
Posted - 2010-11-09 : 14:09:44
|
it is a where close for select statement, here is a full query,I don't have a sample data to check, please check it or post table structures-- 1.If @performanceCriteriaID and @businessObjectiveID are null, just query @tmp IF @performanceCriteriaID IS NULL AND @businessObjectiveID IS NULL BEGIN -- search all user answers without querying many-to-many tables SELECT * FROM @tmp ORDER BY surname, name END -- otherwise, query the many-to-many tables using the passed variables ELSE BEGIN -- query many-to-many table(s) --2. If @performanceCriteriaID is not null, return rows from @tmp where a related row(s) exists in [tbl_BusinessObjectives] SELECT DISTINCT(tmp.answerID), tmp.* FROM @tmp tmp INNER JOIN [tbl_BusinessObjectives] bo ON bo.uiAnswerID = tmp.answerID and bo.boID = @businessObjectiveID where isnull(@businessObjectiveID,0)>0 UNION --3. If @businessObjectiveID is not null, return rows from @tmp where a related row(s) exists in [tbl_PerformanceCriteria] SELECT DISTINCT(tmp.answerID), tmp.* FROM @tmp tmp INNER JOIN [tbl_PerformanceCriteria] pc ON pc.uiAnswerID = tmp.answerID AND pc.pcID = @performanceCriteriaID where ISNULL(@performanceCriteriaID,0)>0 --4. If 2+3 are both not null, return rows from @tmp where a related row(s) exists in [tbl_BusinessObjectives] and [tbl_PerformanceCriteria] --alredy in 2 END |
 |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2010-11-09 : 14:29:51
|
Those WHERE clauses are not needed because they don't do anything. |
 |
|
namman
Constraint Violating Yak Guru
285 Posts |
Posted - 2010-11-09 : 14:37:36
|
quote: I have three tables; one is a table variable, and the other two are many-to-many tables. My query always searches @tmp, but I was wondering if it is possible to only query the other two tables when a variable is passed to query them with. Here's what I'm doing so far which should hopefully explain what I mean... -- if no parameter values passed, then only query table variable IF @performanceCriteriaID IS NULL AND @businessObjectiveID IS NULL BEGIN -- search all user answers without querying many-to-many tables SELECT * FROM @tmp ORDER BY surname, name END -- otherwise, query the many-to-many tables using the passed variables ELSE BEGIN -- query many-to-many table(s) SELECT DISTINCT(tmp.answerID), tmp.* FROM @tmp tmp LEFT OUTER JOIN [tbl_BusinessObjectives] bo ON bo.uiAnswerID = tmp.answerID LEFT OUTER JOIN -- only when needed? [tbl_PerformanceCriteria] pc ON pc.uiAnswerID = tmp.answerID -- only when needed? WHERE (bo.boID = @businessObjectiveID OR @businessObjectiveID IS NULL) AND (pc.pcID = @performanceCriteriaID OR @performanceCriteriaID IS NULL) ORDER BY tmp.surname, tmp.name ENDSo here's the pseudo code I'm aiming for...1. If @performanceCriteriaID and @businessObjectiveID are null, just query @tmp2. If @performanceCriteriaID is not null, return rows from @tmp where a related row(s) exists in [tbl_BusinessObjectives]3. If @businessObjectiveID is not null, return rows from @tmp where a related row(s) exists in [tbl_PerformanceCriteria]4. If 2+3 are both not null, return rows from @tmp where a related row(s) exists in [tbl_BusinessObjectives] and [tbl_PerformanceCriteria]So I guess I'm trying to join only when required. I only return row values from @tmp to prevent duplicate @tmp rows showing when multiple related rows exist in the other table(s). Or am I wasting my time?!?
Hi R,No, you are not wasting your time. You should pay more attention on your query (red part). It likely returns unexpected result.As webfred suggested, you should create 3 sample tables with data, and then the output you want with each condition. That is easier for people to help |
 |
|
R
Constraint Violating Yak Guru
328 Posts |
Posted - 2010-11-10 : 03:44:59
|
Thanks for your feedback. As requested, here's some test data to try and illustrate what I mean.The pseudo code logic is:- If the @boID and @pcID values are null, then simply select all from @tmp
- If @boID is not null, then show all rows from @tmp where a related row exists in @businessObjectives
- If @pcID is not null, then show all rows from @tmp where a related row exists in @performanceCriteria
- if @boID is not null and @pcID is not null, then only show rows from @tmp where related rows exist in both @businessObjectives and @performanceCriteria
What I am trying to avoid is unneccessary use of resources (e.g. joining when a join isn't necessary). I know I could do two separate queries into a table variable and then SELECT DISTINCT (or do a SELECT UNION using the two queries), but just want to check out how other professionals approach this.declare @tmp table ( answerID int identity(1,1), answerText nvarchar(max) )declare @businessObjectives table ( ID int identity(1,1), answerID int not null, boID int not null )declare @performanceCriteria table ( ID int identity(1,1), answerID int not null, pcID int not null )declare @i intdeclare @lastID intSET @i = 1WHILE @i < 500 BEGIN INSERT INTO @tmp (answerText) VALUES ('Placeholder text...') SET @lastID = SCOPE_IDENTITY() INSERT INTO @businessObjectives (answerID, boID) VALUES (@lastID, (SELECT CAST(RAND() * 10 AS INT))) INSERT INTO @businessObjectives (answerID, boID) VALUES (@lastID, (SELECT CAST(RAND() * 10 AS INT))) INSERT INTO @performanceCriteria (answerID, pcID) VALUES (@lastID, (SELECT CAST(RAND() * 10 AS INT))) INSERT INTO @performanceCriteria (answerID, pcID) VALUES (@lastID, (SELECT CAST(RAND() * 10 AS INT))) SET @i = @i + 1 END -- perform selects -----------------------------declare @boID intdeclare @pcID intSET @boID = 5--SET @pcID = 3IF @boID IS NULL AND @pcID IS NULL BEGIN SELECT * FROM @tmp ORDER BY answerID ENDELSE BEGIN SELECT DISTINCT(tmp.answerID), tmp.*, bo.boID, pc.pcID FROM @tmp tmp LEFT OUTER JOIN @businessObjectives bo ON bo.answerID = tmp.answerID LEFT OUTER JOIN -- Unnecessary join when @boID IS NULL! @performanceCriteria pc ON pc.answerID = tmp.answerID -- Unnecessary join when @pcID IS NULL! WHERE (bo.boID = @boID OR @boID IS NULL) AND (pc.pcID = @pcID OR @pcID IS NULL) ORDER BY tmp.answerID END |
 |
|
mikgri
Starting Member
39 Posts |
Posted - 2010-11-10 : 10:07:48
|
Still not sure if it is a result set(s) you wanted, just onother idea:IF @boID IS NULL AND @pcID IS NULL BEGIN SELECT * FROM tmp ORDER BY answerID ENDELSE BEGIN --If @boID is not null, then show all rows from @tmp where a related row exists in @businessObjectives if @boID is not null and @pcID is null begin SELECT DISTINCT(tmp.answerID), tmp.*, bo.boID FROM tmp tmp INNER JOIN businessObjectives bo ON bo.answerID = tmp.answerID and bo.boID=@boID end else --If @pcID is not null, then show all rows from @tmp where a related row exists in @performanceCriteria if @boID is null and @pcID is not null begin SELECT DISTINCT(tmp.answerID), tmp.*, pc.pcID FROM tmp tmp INNER JOIN performanceCriteria pc ON pc.answerID = tmp.answerID and pc.pcID=@pcID end else --if @boID is not null and @pcID is not null, then only show rows from @tmp where related rows exist in both @businessObjectives and @performanceCriteria if @boID is not null and @pcID is not null begin SELECT DISTINCT(tmp.answerID), tmp.*, bo.boid, pc.pcID FROM tmp tmp INNER JOIN businessObjectives bo ON bo.answerID = tmp.answerID and bo.boID=@boID inner join performanceCriteria pc ON pc.answerID = tmp.answerID and pc.pcID=@pcID end END |
 |
|
R
Constraint Violating Yak Guru
328 Posts |
Posted - 2010-11-10 : 10:32:26
|
Hi mikgriThanks for that. Yes, that is the approach I would have opted for should there not be a neater way. It just seems a lot of code doesn't it, and I'd need a seperate logic block for each new variable introduced into the WHERE clause?!? That's the reason for the post anyway; to see if JOINs could be done in a smarter way...! |
 |
|
|
|
|
|
|