Abort subsequent UNION ALL commands if match found

2019-07-28 05:57发布

How do I adapt the query below so that it doesn't perform unnecessary UNION ALL unless the SELECT statement above it doesn't find a match?

SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address = ? AND community = ?
UNION ALL
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text = ? AND community::text LIKE ? 
UNION ALL
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text LIKE ? AND community::text LIKE ?

My coordinates table has columns | ID | ADDRESS | CITY | LATITUDE | LONGITUDE

I'm trying to extract values from latitude and longitude in the most efficient manner, while also performing the strongest queries first, meaning those SELECT statements that will return the most reliable result. If a result is found, return it and discard the remaining queries.

Right now I have all of my queries in an ArrayList which I then loop and execute individually. If a match() is found then I return the resultset. The queries at the top of the list are those that are stricter, using = instead of LIKE, getting gradually less strict if no results are found.

This is obviously inefficient since I'm performing nearly 100 SELECT queries separately, so I've looked into using UNION ALL and my plan is to create one giant query with UNION ALL in between each SELECT statement. However I'm now confused how to abort any subsequent queries if a match is found?

Current approach:

            queryList.add("SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address = ? AND community = ?");
            queryList.add("SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text = ? AND community::text LIKE ?");
            queryList.add("SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text LIKE ? AND community::text LIKE ?")        

            PreparedStatement pStatement = null;
            ResultSet rs = null;
            Connection conn = null;

            for (String currentQuery: queryList) {
                Connection conn = getConnection();
                pStatement = conn.prepareStatement(currentQuery);
                pStatement.setString(1, "742 Evergreen Terrace");
                pStatement.setString(2, "Springfield");
                // execute query
                // if match, break loop and use resultset
            } 

So with UNION ALL, how do I abort if the first SELECT finds a match?

EDIT:

I'm trying this query, but it returns ALL latitutudes and longitudes instead of just the ones which caused the match to be found. How do I alter this to only return the relevant row?

SELECT LATITUDE, LONGITUDE FROM coordinates
WHERE EXISTS(SELECT LATITUDE, LONGITUDE FROM coordinates WHERE 
(address = ? AND community = ?) OR WHERE (address::text = ? AND community::text LIKE ?))

2条回答
Lonely孤独者°
2楼-- · 2019-07-28 06:40

You have to dummy the data. Make the first select some dummy record so that it never fails. or determine what will not fail before you start. You can then use a nested select to remove your dummy row. Basic syntax example.

select Latitude, longitude from
(
select 'dummy data' as Lattitude, 'AltDummy' as Longitude
union all 
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address = ? AND    community = ?
UNION ALL
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text = ? AND community::text LIKE ? 
UNION ALL
SELECT LATITUDE, LONGITUDE FROM coordinates WHERE address::text LIKE ? AND community
) x
where Lattitude <> 'dummy data' and Longitude <> 'AltDummy' 

You will also need to cast your dummy data in the exact same data type as your actual data for this to work right 100% of the time. Submit it to the sql server all as one query and let the sql server do the work.

查看更多
疯言疯语
3楼-- · 2019-07-28 06:46

Other approach:

SELECT LATITUDE, LONGITUDE FROM coordinates 
WHERE (address = ? AND community = ?)
or (text = ? AND community::text LIKE ? )
or (text LIKE ? AND community::text LIKE ?) 

Same net result. Speed differences vary depending on what platform you are working on. But this is likely faster than the previous.

查看更多
登录 后发表回答