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.