问题
In my SP I am creating a temp table #PolicyNumbers and populating it with Policy Numbers based on the parameters that will be supplied to the SP.
CREATE TABLE #PolicyNumbers (PolicyNumber varchar(50))
INSERT INTO #PolicyNumbers SELECT PolicyNumber
FROM PlazaInsuranceWPDataSet
WHERE State IN (SELECT * FROM [dbo].[StringOfStringsToTable](@State,','))
AND Coverage IN (SELECT * FROM [dbo].[StringOfStringsToTable](@Coverage,','))
AND SICCode IN (SELECT * FROM [dbo].[StringOfStringsToTable](@SICCode,','))
Further below in my SP I'm using EXISTS statement to filter only those
PolicyNumbers that been selected based on parameters.
WHERE EXISTS (SELECT PolicyNumber FROM #PolicyNumbers pn WHERE pn.PolicyNumber = piwp.PolicyNumber)
So the result from #PolicyNumbers DOES contain duplicates PolicyNumbers:
Then furthure in my SP I have SELECT statement and the result also contains duplicate PolicyNumbers:
SELECT
PolicyNumber,
Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate,
Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate,
WrittenPremium
FROM PlazaInsuranceWPDataSet
And now I am using EXIST statement:
SELECT
PolicyNumber,
Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate,
Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate,
WrittenPremium
FROM PlazaInsuranceWPDataSet piwp
WHERE EXISTS (SELECT PolicyNumber FROM #PolicyNumbers pn WHERE pn.PolicyNumber = piwp.PolicyNumber)
Is everything correct so far?
If yes, then why do I have slightly different result using SELECT statement and passing same parameters in WHERE clause using IN (@MyParameter)?
SELECT
PolicyNumber,
Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate,
Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate,
WrittenPremium
FROM PlazaInsuranceWPDataSet piwp
WHERE State IN (@State)
AND SICCode IN (@SICCode)
AND Coverage IN (@Coverage)
回答1:
The difference between your two queries, is that the first gets a list of policy numbers where at least one of the rows in the table matches on State, SICode and Coverage. Since there are multiple rows in PlazaInsuranceWPDataSet and each can have different State, SICode and Coverage (presumably), this is not the same as selecting only rows from PlazaInsuranceWPDataSet that match on those three predicates.
Here is a simplified example:
Create Table PlazaInsuranceWPDataSet (
PolicyNumber varchar(1),
State varchar(3))
Insert Into PlazaInsuranceWPDataSet
Values ('A', 'Qld'),
('A', 'NSW');
Create Table #PolicyNumbers (PolicyNumber char(1));
Insert Into #PolicyNumbers
Select PolicyNumber
From PlazaInsuranceWPDataSet
Where State = 'Qld';
-- Returns all policy numbers where at least one row matches the predicate.
Select *
From PlazaInsuranceWPDataSet As piwp
Where Exists (Select 1 From #PolicyNumbers As pn
Where pn.PolicyNumber = piwp.PolicyNumber);
-- Returns only rows of 'A' that match the filter predicate
Select *
From PlazaInsuranceWPDataSet
Where State = 'Qld';
One (and only one) of the rows of policy number 'A' matches the condition so when we write down that policy number in our temp table and then compare to it later we'll get all rows of 'A' back.
来源:https://stackoverflow.com/questions/40942596/how-would-be-the-right-way-to-use-exists-clause