简体   繁体   中英

Combining MySQL queries, with one being an exclusion query

First question on here, so I apologise if I have missed something previously asked, or don't format this well.... My company has a custom CRM + database that I am attempting to improve. We need to find a list of properties that will not have their yearly service renewed. Currently, we do this by first finding properties that will have their service renewed, which is done with the following query:

SELECT DISTINCT 
  j.`property_id` 
FROM
  `jobs` AS j 
  LEFT JOIN `property` AS p 
    ON j.`property_id` = p.`property_id` 
  LEFT JOIN `agency` AS a 
    ON p.`agency_id` = a.`agency_id` 
  INNER JOIN `property_services` AS ps 
    ON (
      j.`property_id` = ps.`property_id` 
      AND j.`service` = ps.`alarm_job_type_id`
    ) 
WHERE ps.`service` = 1 
  AND a.`country_id` = 1 
  AND (
    j.`status` = 'Pending' 
    OR j.`date` IS NULL 
    OR j.`date` = '0000-00-00' 
    OR j.`job_type` = 'Once-off' 
    OR j.`job_type` = '240v Rebook' 
    OR (
      j.`date` >= '2019-04-22' 
      AND j.`job_type` = 'Yearly Maintenance'
    )
  )

Then we find the details we want to display for the user, excluding other items in the process:

SELECT DISTINCT 
  j.`property_id`,
  p.`address_1` AS p_address1,
  p.`address_2` AS p_address2,
  p.`address_3` AS p_address3,
  p.`state` AS p_state,
  p.`postcode` AS p_postcode,
  a.`agency_id`,
  a.`agency_name` 
FROM
  `jobs` AS j 
  LEFT JOIN `property` AS p 
    ON j.`property_id` = p.`property_id` 
  LEFT JOIN `agency` AS a 
    ON p.`agency_id` = a.`agency_id` 
  INNER JOIN `property_services` AS ps 
    ON (
      j.`property_id` = ps.`property_id` 
      AND j.`service` = ps.`alarm_job_type_id`
    ) 
WHERE p.`property_id` NOT IN (INSERT HERE THE IDS YOU GOT FROM THE FIRST QUERY) 
  AND ps.`service` = 1 
  AND p.`deleted` = 0 
  AND p.`agency_deleted` = 0 
  AND a.`status` = 'active' 
  AND a.`country_id` = 1 
ORDER BY j.`property_id` DESC 
LIMIT 0, 50 

Ideally, I'd like to combine these queries, or somehow optimise them, as the page currently takes 2+ minutes to load, even with indexing. Again, my apologies, I am not a database or query expert, pretty sure the degree only included one or two subjects on the matter!

For the record (in case someone would find it helpful), the combined version is:

    SELECT DISTINCT 
  j.`property_id`,
  p.`address_1` AS p_address1,
  p.`address_2` AS p_address2,
  p.`address_3` AS p_address3,
  p.`state` AS p_state,
  p.`postcode` AS p_postcode,
  a.`agency_id`,
  a.`agency_name` 
FROM
  `jobs` AS j 
  LEFT JOIN `property` AS p 
    ON j.`property_id` = p.`property_id` 
  LEFT JOIN `agency` AS a 
    ON p.`agency_id` = a.`agency_id` 
  INNER JOIN `property_services` AS ps 
    ON (
      j.`property_id` = ps.`property_id` 
      AND j.`service` = ps.`alarm_job_type_id`
    ) 
WHERE p.`property_id` NOT IN 
  (SELECT DISTINCT 
    j.`property_id` 
  FROM
    `jobs` AS j 
    LEFT JOIN `property` AS p 
      ON j.`property_id` = p.`property_id` 
    LEFT JOIN `agency` AS a 
      ON p.`agency_id` = a.`agency_id` 
    INNER JOIN `property_services` AS ps 
      ON (
        j.`property_id` = ps.`property_id` 
        AND j.`service` = ps.`alarm_job_type_id`
      ) 
  WHERE ps.`service` = 1 
    AND a.`country_id` = 1 
    AND (
      j.`status` = 'Pending' 
      OR j.`date` IS NULL 
      OR j.`date` = '0000-00-00' 
      OR j.`job_type` = 'Once-off' 
      OR j.`job_type` = '240v Rebook' 
      OR (
        j.`date` >= '2019-05-08' 
        AND j.`job_type` = 'Yearly Maintenance'
      )
    )) 
  AND ps.`service` = 1 
  AND p.`deleted` = 0 
  AND p.`agency_deleted` = 0 
  AND a.`status` = 'active' 
  AND a.`country_id` = 1 
  AND (
    j.`status` != 'Booked' 
    AND j.`status` != 'To Be Booked' 
    AND j.`status` != 'Send Letters' 
    AND j.`status` != 'On Hold' 
    AND j.`status` != 'On Hold - COVID' 
    AND j.`status` != 'Pre Completion' 
    AND j.`status` != 'Merged Certificates'
  ) 
  AND j.`date` > DATE_ADD(NOW(), INTERVAL - 350 DAY) 
ORDER BY j.`property_id` DESC

Someone outside of StackOverflow helped combine, but it didn't help... We ended up having to add a marker and search for that, because this query took 193 seconds to run on our database.

Also, I totally get the requirement to provide a minimum reproducible example, and its my fault for not doing that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM