Dibstar
Dibstar

Reputation: 2364

Replacing In clause with exists

HI Gurus, I'm looking to replace an IN clause with exists, but despite reading other similar cases on here I've not been able to apply them to my dataset.

I am looking to add in a column to my main query which tells me if a fund is found within a separate list, and if it does then label it 'emergency' and if not then 'non-emergency'

The list is defined like so:

select 
f.id
FROM _audit a
INNER JOIN _fund f ON a.article_id = f.id
WHERE a.entity_name = 'Fund'
AND a.Changes LIKE 
'%finance_code2%OldValue>3%'
)
UNION
(
select 
id AS fund_reference
FROM _fund
WHERE (finance_code2 LIKE '3%'
OR finance_code2 LIKE '9%')
AND finance_code2 IS NOT NULL

And so what I am looking for is essentially something like:

SELECT
...Main query here...
,CASE WHEN fund_id IN (list_details) THEN 'emergency' else 'non-emergency' end

I know that it would be more efficient to do something like

SELECT
...Main query here...
,SELECT CASE WHEN EXISTS
(SELECT fund_id FROM list_details WHERE fund_id IS NOT NULL) THEN 'emergency' else 'non-emergency' END

But every time I try it keeps returning false values (saying that funds are contained within the list when they are not)

In case it helps I'm using sql server 2005 and the main query is listed below, where the list_details result (id) is joined onto donation_fund_allocation on list_details.id = donation_fund_allocation.fund_id

As always any clue would be massively appreciated :) Thanks!

Main query

SELECT
don.supporter_id AS contact_id
,don.id AS gift_id
,YEAR(don.date_received) AS calendar_year
,YEAR(don.date_received) - CASE WHEN MONTH(don.date_received) < 4 THEN 1 ELSE 0 END AS financial_year
,don.date_received AS date_received
,don.event_id AS event_id
,SUM(CASE   WHEN don.gift_aid_status <> 4 THEN don.value_gross * ((dfa.percentage) / 100)
            WHEN don.gift_aid_status = 4 AND don.value_net > don.value_gross
            AND don.value_net <> 0       THEN don.value_net  * ((dfa.percentage) / 100)
            ELSE don.value_gross  * ((dfa.percentage) / 100)
            END
        )   AS donation_value
--**List details query to go in here**
FROM donation don WITH (nolock)
INNER JOIN donation_fund_allocation dfa WITH (nolock) ON dfa.donation_id = don.id
WHERE don.supporter_id IS NOT NULL
AND don.status = 4 
AND don.value_gross <> 0
GROUP BY don.supporter_id
,don.id
,don.date_received
,don.event_id

Upvotes: 0

Views: 3779

Answers (2)

ChrisLively
ChrisLively

Reputation: 88072

You could write a function which takes the fund_id and returns an appropriate string value of "emergency" or "non-emergency".

Upvotes: 0

Donnie
Donnie

Reputation: 46933

You need to correlate the exists call with the outer query. As written you are just asking if there exist any rows in list_details where fund_id isn't null

So, what you actually want is

SELECT
...Main query here...
,SELECT CASE WHEN EXISTS
(SELECT 1 FROM list_details WHERE fund_id = outer.fund_id) THEN 'emergency' else 'non-emergency' END

Where outer is the table alias for where fund_id can be found in your main select

Upvotes: 1

Related Questions