问题
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 ?))
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/45023444/abort-subsequent-union-all-commands-if-match-found-h2