简体   繁体   中英

SQL server 2005 - 3 table conundrum

SQL Server 2005 running under 2000 compatibility mode.

I have three tables: Banks , Exceptions and Clients ; a client is allowed to trade with any bank except those associated with him on the exceptions table. Basically they look like the below "schema":

Banks        Exceptions        Clients
-----        ----------        -------
bkID         bkID              
             clID              clID

My question is: how can I find all the clients that have maximum 2 banks with which they're allowed to trade (ie not on the Exceptions table), and one of those two banks being a specific one, always the same for all clients.

An alternate way of rephrasing the question would be: how can I find all the clients that have one specific bank in common (we can choose JPM as an example) and at most one other bank, with which they're allowed to trade?

So far I've created a function that counts how many banks are available given a clID , however I can't really figure out how to add that condition of all the clients having at least JPM in common...

Thanks All!

PS: the function code

ALTER FUNCTION [dbo].[fnGetNbAvailableBanks](@clientID varchar(10))
RETURNS INTEGER
AS
BEGIN 
declare @intReturn integer

set @intReturn = (select 
                        count(*) numBanks
                    from 
                        Banks fxb
                        left outer join Exceptions bx
                            on bx.clID= @clientID and fxb.bkID = bx.bkID
                    where
                        bx.bkID is null
                        and isnull(fxb.bObsolete, 0) = 0)

RETURN @intReturn 
END

The query as I'm trying to run it so far:

select *
from 
    (select
        clID,
        dbo.fnGetNbAvailableBanks(clID) cnt
    from
        Clients) t
where t.cnt <= 2

As you can see as I only return Clients with <= 2 available banks); I need to further filter them to the ones that also contain JPM among those 2 available banks and I'm asking you as I'm looking for an elegant solution.

This should work:

select clID from
(select distinct t1.bkID, t2.clID from Clients t1, Banks t2 
    where t2.bkID not in  
    (select  bkID from  Exceptions t3 where t1.clID = t3.clID ) ) as t1                         
  where clID  not in (select clID from Exceptions where bkID = %yourspecific bankid%)
  group by clID
  having count(*) <= 2

You can use hash tables instead select statment in brackets to make this query work faster.

I changed my function to use EXISTS , like this:

ALTER FUNCTION [dbo].[FNGETNBAVAILABLEBANKS](@clID VARCHAR(10)) 
returns INTEGER 
AS 
  BEGIN 
      DECLARE @intReturn INTEGER 
      SET @intReturn = (SELECT COUNT(*) numBanks 
                        FROM   (SELECT fxb.bkID 
                                FROM   Banks fxb 
                                       LEFT OUTER JOIN Exceptions bx 
                                                    ON bx.clID = @clID 
                                                       AND fxb.bkID = bx.bkID 
                                WHERE  bx.bkID IS NULL 
                                       AND ISNULL(fxb.bObsolete, 0) = 0 
                                       AND EXISTS (SELECT fxb.bkID 
                                                   FROM   Banks fxb 
                                                          LEFT OUTER JOIN 
                                                          Exceptions bx 
                                                                       ON bx.clID = @clID 
                                                                          AND fxb.bkID = bx.bkID 
                                                   WHERE  bx.bkID IS NULL 
                                                          AND fxb.bkID = 'JPM')) a) 
      RETURN @intReturn 
  END  

and the query like this:

select *
from 
(select
    clID,
    dbo.fnGetNbAvailableBanks(clID) cnt
from
    Clients) t
where t.cnt <= 2 and t.cnt > 0

Sorry for the lack of indentation, I don't know why they don't show up... I certainly indented the code...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM