Skip to content
Advertisement

How can I make this select lookup another table and find first match?

I have a database of phone call data from our phone system that I am trying to create a report on. These phone calls match up to a table of internal and external numbers. The report needs to try to match the phone call to an external number in our database first and if there is no match try to match it to an internal number.

I have created a sample data set and db-fiddle, and removed some data to hopefully explain it better:

https://www.db-fiddle.com/f/ofH6sENoce8tGVsoxMejwZ/1

The above example shows how it ends up with a duplicate for a single record because it matches 6220 as the callingPartyNumber and 0412345678 as the finalCalledPartyNumber in each respective select.

This is an example of what I want to see (union has been removed): https://www.db-fiddle.com/f/bVSWESvnKJKvuNefLqH4aU/0

I want a single record for when it either matches a finalCalledPartyNumber first or then a callingPartyNumber. Records that don’t match anything will not be shown.

Updated select using Caius’s example

Select with members table join

Advertisement

Answer

The report needs to try to match the phone call to an external number in our database first and if there is no match try to match it to an internal number.

You can use a pair of left joins for this. Here’s a simpler dataset:

Results:

Few things you need to appreciate about SQL in general:

  • A UNION makes a dataset grow taller (more rows)
  • A JOIN makes a dataset grow wider (more columns)
  • It is easy to compare things on the same row, more difficult to compare things on different rows
  • There isn’t exactly a concept of “doing something now” and “doing something later” – i.e. your “try to match it to external first and if that doesn’t work try match it to internal” isn’t a good way to think about the problem, mentally. The SQL way would be to “match it to external and match it to internal, then preferentially pick the external match, then the internal match, then maybe no match”
  • COALESCE takes a list of arguments and, working left to right, returns the first one that isn’t null. Coupled with LEFT JOIN putting nulls when the match fails, it means we can use it to prefer external matches over internal

Because it’s easier to compare things on the same row, we just try and match the data against the external and internal numbers tables as a direct operation. We use LEFT JOIN so that if the match doesn’t work out, at least it doesn’t cause the row to disappear..

So you join both numbers tables in and the matches either work out for external (and you will pick external), work out for internal but not external (and you will pick internal), work out for both int and ext (and you will pick ext over int), or don’t work out (and you might have a message to say No Match)


It should be pointed out that the COALESCE approach only really works well if the data won’t naturally contain nulls. If the data looked like this:

Then this will be the result:

Even though the join succeeded, the presence of a NULL in the ExternalNumber.Message means the InternalNumber.Message is used instead, and this might not be correct. We can solve this by using CASE WHEN instead, to test for a column that definitely won’t be null when a record matches:

Because we test the column that is the key for the join the only way we can get a null there is when the join fails to find a match.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement