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:
CREATE TABLE `cdr` (
`callnumber` int(11) NOT NULL,
`origLegCallIdentifier` int(11) NOT NULL,
`dateTimeOrigination` datetime NOT NULL,
`callType` varchar(50) NOT NULL,
`chargeable` varchar(10) NOT NULL,
`callCharge` decimal(10,2) NOT NULL,
`origNodeId` int(11) NOT NULL,
`destLegIdentifier` int(11) NOT NULL,
`destNodeId` int(11) NOT NULL,
`callingPartyNumber` varchar(50) NOT NULL,
`callingPartyNumberPartition` varchar(50) NOT NULL,
`callingPartyNumberState` varchar(10) NOT NULL,
`callingPartyNumberSite` varchar(30) NOT NULL,
`originalCalledPartyNumber` varchar(50) NOT NULL,
`originalCalledPartyNumberPartition` varchar(50) NOT NULL,
`finalCalledPartyNumber` varchar(50) NOT NULL,
`finalCalledPartyNumberPartition` varchar(50) NOT NULL,
`lastRedirectDn` varchar(50) NOT NULL,
`lastRedirectDnPartition` varchar(50) NOT NULL,
`dateTimeConnect` datetime DEFAULT NULL,
`dateTimeDisconnect` datetime NOT NULL,
`duration` int(11) NOT NULL,
`origDeviceName` varchar(129) NOT NULL,
`destDeviceName` varchar(129) NOT NULL,
`origIpv4v6Addr` varchar(64) NOT NULL,
`destIpv4v6Addr` varchar(64) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `cdr` (`callnumber`, `origLegCallIdentifier`, `dateTimeOrigination`, `callType`, `chargeable`, `callCharge`, `origNodeId`, `destLegIdentifier`, `destNodeId`, `callingPartyNumber`, `callingPartyNumberPartition`, `callingPartyNumberState`, `callingPartyNumberSite`, `originalCalledPartyNumber`, `originalCalledPartyNumberPartition`, `finalCalledPartyNumber`, `finalCalledPartyNumberPartition`, `lastRedirectDn`, `lastRedirectDnPartition`, `dateTimeConnect`, `dateTimeDisconnect`, `duration`, `origDeviceName`, `destDeviceName`, `origIpv4v6Addr`, `destIpv4v6Addr`) VALUES
(52004, 69637277, '2020-08-31 03:05:05', 'outbound-national', 'yes', '0.00', 4, 69637278, 4, '6220', 'PT_INTERNAL', 'NSW', 'Site A', '0412345678', 'PT_NATIONAL_TIME_RESTRICT', '0412345678', 'PT_NATIONAL_TIME_RESTRICT', '0412345678', 'PT_NATIONAL_TIME_RESTRICT', NULL, '2020-08-31 03:05:08', 0, 'SEP00XXXXX', 'XXXXX', '1.1.1.1', '1.1.1.1');
CREATE TABLE `numbers` (
`numberid` int(11) NOT NULL,
`number` varchar(30) NOT NULL,
`memberid` int(11) NOT NULL,
`type` enum('internal','external') NOT NULL,
`description` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `numbers` (`numberid`, `number`, `memberid`, `type`, `description`) VALUES
(1555, '0412345678', 436, 'internal', ''),
(1556, '6220', 437, 'external', '');
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
DATE(CONVERT_TZ(cdr.dateTimeOrigination,'+00:00',@@global.time_zone)) as 'Date',
TIME(CONVERT_TZ(cdr.dateTimeOrigination,'+00:00',@@global.time_zone)) as 'Time',
cdr.callType,
cdr.callingPartyNumberState,
cdr.callingPartyNumber,
COALESCE(finalcalledparty.memberid, callingparty.memberid, originalcalledparty.memberid, 'No Match') as MemberID,
cdr.originalCalledPartyNumber,
cdr.finalCalledPartyNumber,
CONCAT(MOD(HOUR(SEC_TO_TIME(cdr.duration)), 24), ':', LPAD(MINUTE(SEC_TO_TIME(cdr.duration)),2,0), ':', LPAD(second(SEC_TO_TIME(cdr.duration)),2,0)) as 'duration',
cdr.callCharge
FROM `cdr`
LEFT JOIN numbers finalcalledparty ON finalcalledparty.number = cdr.finalCalledPartyNumber
LEFT JOIN numbers callingparty ON callingparty.number = cdr.callingPartyNumber
LEFT JOIN numbers originalcalledparty ON originalcalledparty.number = cdr.OriginalCalledPartyNumber
WHERE (cdr.callType LIKE '%outbound%' OR cdr.callType LIKE '%transfer%' OR cdr.callType LIKE '%forward%')
ORDER BY Date DESC, Time DESC
Select with members table join
SELECT
DATE(CONVERT_TZ(cdr.dateTimeOrigination,'+00:00',@@global.time_zone)) as 'Date',
TIME(CONVERT_TZ(cdr.dateTimeOrigination,'+00:00',@@global.time_zone)) as 'Time',
cdr.callType,
'Calling' as ChargeType,
cdr.callingPartyNumberState,
cdr.callingPartyNumber,
COALESCE(finalcalledmember.name, callingmember.name, 'No Match') as MemberName,
cdr.finalCalledPartyNumber,
CONCAT(MOD(HOUR(SEC_TO_TIME(cdr.duration)), 24), ':', LPAD(MINUTE(SEC_TO_TIME(cdr.duration)),2,0), ':', LPAD(second(SEC_TO_TIME(cdr.duration)),2,0)) as 'duration',
cdr.callCharge
FROM `cdr`
LEFT JOIN numbers callingparty ON callingparty.number = cdr.callingPartyNumber
LEFT JOIN numbers finalcalledparty ON finalcalledparty.number = cdr.finalCalledPartyNumber
LEFT JOIN members callingmember ON callingmember.memberid = callingparty.memberid
LEFT JOIN members finalcalledmember ON finalcalledmember.memberid = finalcalledparty.memberid
WHERE (callType LIKE '%outbound%' OR callType LIKE '%transfer%' OR callType LIKE '%forward%') AND DATE(CONVERT_TZ(cdr.dateTimeOrigination,'+00:00',@@global.time_zone)) = '2020-09-01'
ORDER BY Date DESC, Time DESC