views:

118

answers:

3

I have a table (that relates to a number of other tables) where I would like to filter ONE of the columns (RequesterID) - that column will be a combobox where only people that are not sales people should be selectable.

Here is the "unfiltered" query, lets call it QUERY 1:

SELECT RequestsID, RequesterID, ProductsID
FROM dbo.Requests

If using a separate query, lets call it QUERY 2, to filter RequesterID (which is a People related column, connected to People.PeopleID), it would look like this:

SELECT     People.PeopleID
FROM         People INNER JOIN
                  Roles ON People.RolesID = Roles.RolesID INNER JOIN
                  Requests ON People.PeopleID = Requests.RequesterID
WHERE     (Roles.Role <> N'SalesGuy')
ORDER BY Requests.RequestsID

Now, is there a way of "merging" the QUERY 2 into QUERY 1?

(dbo.Requests in QUERY 1 has RequesterID populated as a Foreign Key from dbo.People, so no problem there... The connections are all right, just not know how to write the SQL query!)

UPDATE

Trying to explain what I mean in a bit more... :

The result set should be a number of REQUESTS - and the number of REQUESTS should not be limited by QUERY 2. QUERY 2:s only function is to limit the selectable subset in column Requests.RequesterID - and no, it´s not that clear, but in the C# VS2008 implementation I use Requests.RequesterID to eventually populate a ComboBox with [Full name], which is another column in the People table - and in that column I don´t want SalesGuy to show up as possible to select; here I´m trying to clear it out EVEN MORE... (but with wrong syntax, of course)

SELECT RequestsID, (RequesterID WHERE RequesterID != 8), ProductsID
FROM dbo.Requests

Yes, RequesterID 8 happens to be the SalesGuy :-)

A: 

Following clarification. Something like this?

SELECT RequestsID, RequesterID, ProductsID, 
CAST(CASE WHEN Roles.Role IS NULL THEN 0 ELSE 1 END AS BIT) AS Selectable
FROM dbo.Requests
LEFT OUTER JOIN 
    People ON People.PeopleID = Requests.RequesterID
LEFT OUTER JOIN 
    Roles ON People.RolesID = Roles.RolesID AND  (Roles.Role <> N'SalesGuy')
Martin Smith
I think this is exactly what I wanted, Martin! I´ll test it out for a little while... I will be back by soon ;-)
Kent S. Clarkson
Well, now I´ve tried to test it out, but my environment doesn´t like it, even though I think that your logic is perfect - I use SQL Server 2005, and VS Studio 2008. Actually I don´t know if it´s environmental, but the error message is: "Dynamic SQL generation is not supported against multible base tables" - and there ARE a couple of base tables involved... hmmm... what now?
Kent S. Clarkson
No problem regarding Generating Select statements, but when it comes to Insert, Update and Delete, I get the message: "Dynamic SQL generation is not supported against multible base tables" (to be more clear) - yes, and as I mentioned nothing about my environment in my initial question, as I thought it was a pure SQL thing, this is probably out of scope, but anyway - sadly enough - I can´t test out your very nice sql query.
Kent S. Clarkson
What are you binding it too? A strongly typed dataset? You might need to create your own custom Insert/Update/Delete procedures or parameterised statements and use those rather than get it to auto generate them. Do you need Insert/Update/Delete wired up anyway if this is just to be displayed in a list box?
Martin Smith
Yes, I need Insert/Update/Delete if a row should be updated or deleted... Not sure if the DataSet is strongly typed or not - but a DataSet it is - I went for "default settings" when setting up the project. And don´t know where to look it up in the menus... OK, have to run - I wont be able to watch updates for a good while now. But when it comes to the problems I met, it has NOT to do with the CAST or SalesGuy parameter - I made some trouble shooting. Maybe it´s because I´m trying to edit the "original" Fill, GetData on the TableAdapter?
Kent S. Clarkson
I did yet another update to my initial question...
Kent S. Clarkson
You might be better off starting another question on this. It seems to have started off as a database question and morphed into a .NET one!
Martin Smith
You´re probably right... but I think I give up now :-)
Kent S. Clarkson
+1  A: 

here is a very comprehensive article on how to handle this topic:

Dynamic Search Conditions in T-SQL by Erland Sommarskog

it covers all the issues and methods of trying to write queries with multiple optional search conditions. This main thing you need to be concerned with is not the duplication of code, but the use of an index. If your query fails to use an index, it will preform poorly. There are several techniques that can be used, which may or may not allow an index to be used.

here is the table of contents:

  Introduction
      The Case Study: Searching Orders
      The Northgale Database
   Dynamic SQL
      Introduction
      Using sp_executesql
      Using the CLR
      Using EXEC()
      When Caching Is Not Really What You Want
   Static SQL
      Introduction
      x = @x OR @x IS NULL
      Using IF statements
      Umachandar's Bag of Tricks
      Using Temp Tables
      x = @x AND @x IS NOT NULL
      Handling Complex Conditions
   Hybrid Solutions – Using both Static and Dynamic SQL
      Using Views
      Using Inline Table Functions
   Conclusion
   Feedback and Acknowledgements
   Revision History

if you are on the proper version of SQL Server 2008, there is an additional technique that can be used, see: Dynamic Search Conditions in T-SQL Version for SQL 2008 (SP1 CU5 and later)

If you are on that proper release of SQL Server 2008, you can just add OPTION (RECOMPILE) to the query and the local variable's value at run time is used for the optimizations.

Consider this, OPTION (RECOMPILE) will take this code (where no index can be used with this mess of ORs):

WHERE
    (@search1 IS NULL or Column1=@Search1)
    AND (@search2 IS NULL or Column2=@Search2)
    AND (@search3 IS NULL or Column3=@Search3)

and optimize it at run time to be (provided that only @Search2 was passed in with a value):

WHERE
    Column2=@Search2

and an index can be used (if you have one defined on Column2)

KM
+1  A: 

How about this? Since the query already joins on the requests table you can simply add the columns to the select-list like so :

SELECT     Requests.RequestsID, Requests.RequesterID, Requests.ProductsID
FROM         People INNER JOIN
                  Roles ON People.RolesID = Roles.RolesID INNER JOIN
                  Requests ON People.PeopleID = Requests.RequesterID
WHERE     (Roles.Role <> N'SalesGuy')
ORDER BY Requests.RequestsID

You can in fact select any column from any of the joined tables (Roles, Requests, People, etc.)

It becomes clear if you just replace People.PeopleId with * and it will show you everything retrieved from the tables.

Cobusve
I thought that as well. I'm still not really sure of the requirement having read the question about 3 times though! I can't see any dynamic column requirement but am probably missing something.
Martin Smith
@Cobusve, `SELECT *` is a bad practice to use. it will waste resources returning column that are not used, and it prevents the use of a covering index. @Martain Smith, I too am not really sure what the OP means by 'merge', what should the result set be? how to filter? etc.
KM
The result set should be a number of REQUESTS - and the number of REQUESTS should not be limited by QUERY 2. QUERY 2:s only function is to limit the selectable subset in column Requests.RequesterID - and no, it´s not that clear, but in the C# VS2008 implementation I use Requests.RequesterID to eventually populate a ComboBox with [Full name], which is another column in the People table...
Kent S. Clarkson