Skip to main content
changed order of wording
Source Link

I don't know sql-server know well enough to state whether it works this way or not, but in theory there is no way you can say that one part of the union is evaluated before another. I.e. even though you have a perfect match, you may still end up with an approximate one.

The optimizer may be smart enough to understand where to stop. It is at least obligated to evaluate t1 before t2 and so forth.

I don't sql-server know well enough to state whether it works this way or not, but in theory there is no way you can say that one part of the union is evaluated before another. I.e. even though you have a perfect match, you may still end up with an approximate one.

The optimizer may be smart enough to understand where to stop.

I don't know sql-server well enough to state whether it works this way or not, but in theory there is no way you can say that one part of the union is evaluated before another. I.e. even though you have a perfect match, you may still end up with an approximate one.

The optimizer may be smart enough to understand where to stop. It is at least obligated to evaluate t1 before t2 and so forth.

deleted 23 characters in body
Source Link
 with t1 as (
        -- Unique suburb-postcode-state combinations
        SELECT  1 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
                ,s.Postcode
                ,Geocode_DID = 4 -- Exact match by unique Postcode, Suburb and State
                ,s.Geocode_Latitude
                ,s.Geocode_Longitude
        FROM geocode.tSuburbs_XX s
        INNER JOIN [geocode].[tGeocode_Methods] gm
            ON s.Geocode_DID = gm.Geocode_DID

        WHERE s.[Is_Active] = 1
        AND s.[Suburb] = @Suburb
        AND s.[State] = @State
        AND s.[Postcode] = @Postcode
        -- Only suburbs that are geocoded with methods that can be used for geocoding customers
        AND gm.[Can_Use_For_VIP] = 1
), t2 as (
        - -- Unique suburb-postcode combinations
        SELECT  2 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T1 )
), t3 as (
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T1 UNION SELECT 1 FROM T2 )
)
select * from t1
union all
select * from t2
union all
[...]
 with t1 as (
        -- Unique suburb-postcode-state combinations
        SELECT  1 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
                ,s.Postcode
                ,Geocode_DID = 4 -- Exact match by unique Postcode, Suburb and State
                ,s.Geocode_Latitude
                ,s.Geocode_Longitude
        FROM geocode.tSuburbs_XX s
        INNER JOIN [geocode].[tGeocode_Methods] gm
            ON s.Geocode_DID = gm.Geocode_DID

        WHERE s.[Is_Active] = 1
        AND s.[Suburb] = @Suburb
        AND s.[State] = @State
        AND s.[Postcode] = @Postcode
        -- Only suburbs that are geocoded with methods that can be used for geocoding customers
        AND gm.[Can_Use_For_VIP] = 1
), t2 as (
        - -- Unique suburb-postcode combinations
        SELECT  2 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T1 )
), t3 as (
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T1 UNION SELECT 1 FROM T2 )
)
select * from t1
union all
select * from t2
union all
[...]
 with t1 as (
        -- Unique suburb-postcode-state combinations
        SELECT  1 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
                ,s.Postcode
                ,Geocode_DID = 4 -- Exact match by unique Postcode, Suburb and State
                ,s.Geocode_Latitude
                ,s.Geocode_Longitude
        FROM geocode.tSuburbs_XX s
        INNER JOIN [geocode].[tGeocode_Methods] gm
            ON s.Geocode_DID = gm.Geocode_DID

        WHERE s.[Is_Active] = 1
        AND s.[Suburb] = @Suburb
        AND s.[State] = @State
        AND s.[Postcode] = @Postcode
        -- Only suburbs that are geocoded with methods that can be used for geocoding customers
        AND gm.[Can_Use_For_VIP] = 1
), t2 as (
        - -- Unique suburb-postcode combinations
        SELECT  2 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T1 )
), t3 as (
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T2 )
)
select * from t1
union all
select * from t2
union all
[...]
Source Link

I don't sql-server know well enough to state whether it works this way or not, but in theory there is no way you can say that one part of the union is evaluated before another. I.e. even though you have a perfect match, you may still end up with an approximate one.

You can however force this behavior by adding a priority to each part of the union and order by that. Something like:

SELECT TOP 1 *
FROM (
        -- Unique suburb-postcode-state combinations
        SELECT  1 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
                ,s.Postcode
                ,Geocode_DID = 4 -- Exact match by unique Postcode, Suburb and State
                ,s.Geocode_Latitude
                ,s.Geocode_Longitude
        FROM geocode.tSuburbs_XX s
        INNER JOIN [geocode].[tGeocode_Methods] gm
            ON s.Geocode_DID = gm.Geocode_DID

        WHERE s.[Is_Active] = 1
        AND s.[Suburb] = @Suburb
        AND s.[State] = @State
        AND s.[Postcode] = @Postcode
        -- Only suburbs that are geocoded with methods that can be used for geocoding customers
        AND gm.[Can_Use_For_VIP] = 1


        UNION ALL


        -- -- Unique suburb-postcode combinations
        SELECT  2 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
        [...]
) t
order by prio

Now you will get - one of - the row with the smallest prio in return. Note that the DBMS may still evaluate other options so there is no guarantee that it will perform better.

Another idea is to pipeline the parts via CTE's in the order of preference:

 with t1 as (
        -- Unique suburb-postcode-state combinations
        SELECT  1 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
                ,s.Postcode
                ,Geocode_DID = 4 -- Exact match by unique Postcode, Suburb and State
                ,s.Geocode_Latitude
                ,s.Geocode_Longitude
        FROM geocode.tSuburbs_XX s
        INNER JOIN [geocode].[tGeocode_Methods] gm
            ON s.Geocode_DID = gm.Geocode_DID

        WHERE s.[Is_Active] = 1
        AND s.[Suburb] = @Suburb
        AND s.[State] = @State
        AND s.[Postcode] = @Postcode
        -- Only suburbs that are geocoded with methods that can be used for geocoding customers
        AND gm.[Can_Use_For_VIP] = 1
), t2 as (
        - -- Unique suburb-postcode combinations
        SELECT  2 as prio
                ,s.Suburb_DID
                ,s.Suburb
                ,s.State
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T1 )
), t3 as (
        [...]
        WHERE NOT EXISTS ( SELECT 1 FROM T1 UNION SELECT 1 FROM T2 )
)
select * from t1
union all
select * from t2
union all
[...]

The optimizer may be smart enough to understand where to stop.