I need a MySQL Query Guru

Hi there

I have a database query that is matching a set of ids from 10 categories for a job, against the equivelant 10 categories for candidates. The output is a list of job_id’s that the criteria matches.

I have this working as an ‘OR’ but I need it to work as an AND, but when a certain category is null/empty it should ignore or pass it.

When I configure this as an AND I get no results, when I know there is a matching result.

the goal is for the results to get more and more narrow as you select more items, and more and more broad when you select less. The OR just returns poor matches, and too many.

I had this working in a POSTGRES script I can share, but, there are some functions in Postgres that don’t perform in MySQL.

I’d like to provide the output data, the current working query and have a guru update this to work as per the requirement.

Please respond here or send me a DM.

Hey @mgaussie,

It would be nice if you have posted your query builder schema and its condition that restricts the results and your client-side way of getting these results.

My very fast response would be that you are talking about “ids” so make sure you are not comparing string with numeric data…
Please upload screenshots so we can check my friend

1 Like

Hey @famousmag I didn’t post the query wrc as I’m prepared to pay an expert for the work - but happy to share in my AM if you’d like to take a look.

The query works as an OR so I don’t believe the data types are wrong - but I’ll share in the Am. Thanks for your reply.

1 Like

Sorry my friend… Didn’t understand your inquiry and I was happy to help if I could.
I am not an expert or guru so I’m ready to step back If I should :blush:

1 Like

Hi mgaussie, happy to have a look at the query. If you wish to send me a DM with the data etc., then that’s okay as well.

Hi guys,

So here is my query:

select distinct `job_posts`.`id` as `job_post_id` from `job_posts` left join `job_post_job_level` on `job_post_job_level`.`job_post_id` = `job_posts`.`id` left join `job_post_job_post_tech` on `job_post_job_post_tech`.`job_post_id` = `job_posts`.`id` left join `job_post_job_post_cat_related` on `job_post_job_post_cat_related`.`job_post_id` = `job_posts`.`id` left join `job_post_job_locations` on `job_post_job_locations`.`job_post_id` = `job_posts`.`id` where (`job_posts`.`approved` = ? and ((`job_post_job_post_tech`.`tech` in ?) or (`job_post_job_level`.`level` in ?) or (`job_post_job_post_cat_related`.`job_sub_category` in ?) or (`job_post_job_locations`.`remote_location_id` in ?) or (`job_post_job_locations`.`non_remote_location_id` in ?)))

Here is the breakdown of what I’m trying to accomplish:

I’m building a matching engine, using MySQL.

The query should match the integer from each of the candidates preferences (e.g. tech, location, work_type) with the relevant integer from the jobs preferences (tech, location, work_type). The preferences are held in a number of sub tables which link to the main table (e.g. job or candidate). The match should output job_id which I then insert into a recommendatons table along with the candidate.id.

The data structure is similar for both, a main table (candidate / job) and then sub tables that hold the criteria identifier as an integer, and the ref to either the candidate or the job e.g:

Candidate (main table, with most of the text content e.g. name, position title etc.)
Candidate_tech_preference_sub_table

  • id
  • candidate_id
  • tech_id

And then I have the job:
Job (main table, with most of the text content e.g. job_title, job_description etc. )
Job_tech_sub_table

  • id
  • job_id
  • tech_id

What I’m doing in the Server Connect is first query the candidate to get all candidate data, and then I’m sing a series of conditions to check if the data exists (as not every field will always be presented) and then using a setval for this, I then is an ‘IN’ condition to match against the integers in the set val.

Here is an example of a setval used in this way:

"setval_location": [
    16,
    18
],

I have also built a custom module to handle the data in an way easier to match against, here is an example of the output:

    "sqlprep": {
            "candidate_id": 1,
            "min_salary": "110000.00",
            "user_role_level_join": null,
            "user_location_join": [
                11,
                12
            ],
            "user_industry_preferences": null,
            "user_company_size_join": null,
            "user_tech_preferences": null,
            "user_roleType_preferences": null,
            "user_role_priorities_join": null,
            "user_language_join": null
        }

The query does not fail, it works fine with OR conditions. But OR conditions are not desirable due to the nature of the matches. Instead I must use a AND query.

The match must get more narrow as more criteria are included and broader as there is less.

E.g.

If the candidate preference is ‘react’ for tech, and ‘sydney’ for locaton, then we must match all jobs with those criteria as a minimum.

What I have noticed is that with this query with the OR condition, it will work as long as there is at least one criteria, but it will return no results if none are present.

I’m assuming this is where the issue exists for the AND. I need the MySQL Query to be able run the query even without all the data.

I had this working with Postgres, but the syntax between the two differs and I javen’t been able to replicate the same outcome:

    SELECT job_posts.id AS job_id
    FROM job_posts
    WHERE (
        COALESCE(array_length(:P5::integer[], 1), 0) = 0
        OR EXISTS (
            SELECT 1
            FROM job_post_job_locations
            WHERE job_post_job_locations.job_post_id = job_posts.id
            AND job_post_job_locations.remote_location_id = ANY(:P5)
        )
    )
    AND (
        COALESCE(array_length(:P9::integer[], 1), 0) = 0
        OR EXISTS (
            SELECT 1
            FROM job_post_job_locations
            WHERE job_post_job_locations.job_post_id = job_posts.id
            AND job_post_job_locations.non_remote_location_id = ANY(:P9)
        )
    )
    AND (
        COALESCE(array_length(:P6::integer[], 1), 0) = 0
        OR EXISTS (
            SELECT 1
            FROM job_posts
            INNER JOIN companies ON companies.id = job_posts.company_id
            INNER JOIN "company_sectorTags_join" ON "company_sectorTags_join".company_id = companies.id
            WHERE job_posts.id = job_posts.id
            AND "company_sectorTags_join".sector_tag_id = ANY(:P6)
        )
    )
    AND (
        COALESCE(array_length(:P4::integer[], 1), 0) = 0
        OR EXISTS (
            SELECT 1
            FROM job_post_job_post_cat_related
            WHERE job_post_job_post_cat_related.job_post_id = job_posts.id
            AND job_post_job_post_cat_related.job_sub_category = ANY(:P4)
        )
    )
    AND (
        COALESCE(array_length(:P2::integer[], 1), 0) = 0
        OR EXISTS (
            SELECT 1
            FROM job_posts
            INNER JOIN companies ON companies.id = job_posts.company_id
            WHERE job_posts.id = job_posts.id
            AND companies.company_staff_size_ref = ANY(:P2)
        )
    )
    AND (
        COALESCE(array_length(:P1::integer[], 1), 0) = 0
        OR EXISTS (
            SELECT 1
            FROM job_post_job_post_tech
            WHERE job_post_job_post_tech.job_post_id = job_posts.id
            AND job_post_job_post_tech.tech = ANY(:P1)
        )
    )
    AND (
        COALESCE(array_length(:P3::integer[], 1), 0) = 0
        OR EXISTS (
            SELECT 1
            FROM job_post_job_level
            WHERE job_post_job_level.job_post_id = job_posts.id
            AND job_post_job_level.level = ANY(:P3)
        )
    );

I have been playing around a bit more today, using ChatGPT and here is a query we’ve come up with - but It’s still failing, it seems on the :P5 parameter that passes (16,18) to the query. SQL Query:

    SELECT DISTINCT job_posts.id AS job_post_id
    FROM job_posts
    LEFT JOIN job_post_job_level ON job_post_job_level.job_post_id = job_posts.id
    LEFT JOIN job_post_job_post_tech ON job_post_job_post_tech.job_post_id = job_posts.id
    LEFT JOIN job_post_job_post_cat_related ON job_post_job_post_cat_related.job_post_id = job_posts.id
    LEFT JOIN job_post_job_locations ON job_post_job_locations.job_post_id = job_posts.id
    WHERE job_posts.approved = 1
    AND (
        EXISTS (
            SELECT 1
            FROM job_post_job_locations
            WHERE job_post_job_locations.job_post_id = job_posts.id
            AND job_post_job_locations.remote_location_id IN (:P5)
        )
        OR :P5 IS NULL  -- Assuming :remoteLocationArray is the parameter you pass in
    )
    AND (
        -- Your other conditions here, similar to the one above, for example:
        :P1 IS NULL
        OR EXISTS (
            SELECT 1
            FROM job_post_job_locations
            WHERE job_post_job_locations.job_post_id = job_posts.id
            AND job_post_job_locations.non_remote_location_id IN (:P1)
        )
    )
    AND (
        :P5 IS NULL
        OR EXISTS (
            SELECT 1
            FROM job_post_job_post_cat_related
            WHERE job_post_job_post_cat_related.job_post_id = job_posts.id
            AND job_post_job_post_cat_related.job_sub_category IN (:P5)
        )
    )
    AND (
        :P5 IS NULL
        OR EXISTS (
            SELECT 1
            FROM job_post_job_post_tech
            WHERE job_post_job_post_tech.job_post_id = job_posts.id
            AND job_post_job_post_tech.tech IN (:P5)
        )
    )
    AND (
        :P5 IS NULL
        OR EXISTS (
            SELECT 1
            FROM job_post_job_level
            WHERE job_post_job_level.job_post_id = job_posts.id
            AND job_post_job_level.level IN (:P5)
        )
    );

Console Error:

`"SELECT DISTINCT job_posts.id AS job_post_id\nFROM job_posts\nLEFT JOIN job_post_job_level ON job_post_job_level.job_post_id = job_posts.id\nLEFT JOIN job_post_job_post_tech ON job_post_job_post_tech.job_post_id = job_posts.id\nLEFT JOIN job_post_job_post_cat_related ON job_post_job_post_cat_related.job_post_id = job_posts.id\nLEFT JOIN job_post_job_locations ON job_post_job_locations.job_post_id = job_posts.id\nWHERE job_posts.approved = 1\nAND (\n    EXISTS (\n        SELECT 1\n        FROM job_post_job_locations\n        WHERE job_post_job_locations.job_post_id = job_posts.id\n        AND job_post_job_locations.remote_location_id IN (NULL)\n    )\n    OR NULL IS NULL  -- Assuming :remoteLocationArray is the parameter you pass in\n)\nAND (\n    -- Your other conditions here, similar to the one above, for example:\n    16, 18 IS NULL\n    OR EXISTS (\n        SELECT 1\n        FROM job_post_job_locations\n        WHERE job_post_job_locations.job_post_id = job_posts.id\n        AND job_post_job_locations.non_remote_location_id IN (16, 18)\n    )\n)\nAND (\n    NULL IS NULL\n    OR EXISTS (\n        SELECT 1\n        FROM job_post_job_post_cat_related\n        WHERE job_post_job_post_cat_related.job_post_id = job_posts.id\n        AND job_post_job_post_cat_related.job_sub_category IN (NULL)\n    )\n)\nAND (\n    NULL IS NULL\n    OR EXISTS (\n        SELECT 1\n        FROM job_post_job_post_tech\n        WHERE job_post_job_post_tech.job_post_id = job_posts.id\n        AND job_post_job_post_tech.tech IN (NULL)\n    )\n)\nAND (\n    NULL IS NULL\n    OR EXISTS (\n        SELECT 1\n        FROM job_post_job_level\n        WHERE job_post_job_level.job_post_id = job_posts.id\n        AND job_post_job_level.level IN (NULL)\n    )\n);\n - Operand should contain 1 column(s)"`

Any help is really appreciated here and happy to pay for it.

use coalesce.

@mgaussie, I don’t have the time or headspace to understand your particular query need here…

… but I create some really bloody complex queries by combining MySQL views and sometimes unions to create a result which may have excessive data, and then use further steps in a server action to refine them down to exactly what I need.

Sometimes a different way of approaching the problem can really help!

2 Likes

Thanks @Antony! This is likely the path I’ll take if I can’t get the MySQL version of the query working soon!

Thanks anofm - I’ve tried a similar function:

SELECT job_posts.id AS job_id
FROM job_posts
WHERE (
(:P5 IS NULL OR LENGTH(:P5) = 0)
OR EXISTS (
SELECT 1
FROM job_post_job_locations
WHERE job_post_job_locations.job_post_id = job_posts.id
AND FIND_IN_SET(job_post_job_locations.remote_location_id, :P5)
)
)
AND (
(:P9 IS NULL OR LENGTH(:P9) = 0)
OR EXISTS (
SELECT 1
FROM job_post_job_locations
WHERE job_post_job_locations.job_post_id = job_posts.id
AND FIND_IN_SET(job_post_job_locations.non_remote_location_id, :P9)
)
)

but no luck…

after further trial and error, it seems that the query i’m constructing isn’t able to process an empty array, or value.

Here is an output from the console:

setval_remotelocation: []

that I’m using as a parameter.

If anyone knows how to solve this, and has the time, send me a DM we can work something out.

Pleasure @mgaussie!

The other thing I do is develop the views in MySQL Workbench… it’s way easier than trying to keep calling it from a Wappler Server Action!

So, question why are you using left join and not inner join?: and I would say since location is such a critical part of the query you should probably have that in a table by itself and use the location table as your starting point as a category table that reference all the foreign key of each table. This way you only call location table by location then filter from there. We can get on call if you like just let me know.

2 Likes

I found Views in MySQL very valuable over the years.
Querying already defined Views instead of depending on One complex Query to assemble temporary tables, so to speak, was always a faster and more efficient use of server side resources.

1 Like

have you tried somethign like this:

select distinct A.`id` as `job_post_id`
from job_posts A
left join job_post_job_level B on B.`job_post_id` = A.`id`
left join job_post_job_post_tech C on C.`job_post_id` = A.`id`
left join job_post_job_post_cat_related D on D.`job_post_id` = A.`id`
left join job_post_job_locations E on E.`job_post_id` = A.`id`
where A.`approved` = ?
AND (C.`tech` in (:tech) OR :tech IS NULL)
AND (B.`level` in (:level) OR :level IS NULL)
AND (D.`job_sub_category` in (:job_sub_category) OR :job_sub_category IS NULL)
AND (E.`remote_location_id` in (:remote_location_id) OR :remote_location_id IS NULL)
AND (E.`non_remote_location_id` in (:non_remote_location_id) OR :non_remote_location_id IS NULL)

I can’t test the query from @nshkrsh but just for brevity & “standard” mysql it LOOKS good.
I’ve found these guys very knowledgable in the past.

Hi all, apologies for the delay on my end - daycare germs wiped me out for a week!

I ended up solving it, by tackling each section one by one and also preparing the data with a series of conditions and .toString() setvals. If it’s of any use to anyone, here is the SQL query that is working well:

SELECT job_posts.id AS job_post_id
FROM job_posts
WHERE (
    (:P5 IS NULL OR LENGTH(:P5) = 0)
    OR EXISTS (
        SELECT 1
        FROM job_post_job_locations
        WHERE job_post_job_locations.job_post_id = job_posts.id
        AND FIND_IN_SET(job_post_job_locations.non_remote_location_id, :P5)
    )
)
AND (
    
  (:P9 IS NULL OR LENGTH(:P9) = 0)
    OR EXISTS (
        SELECT 1
        FROM job_post_job_locations
        WHERE job_post_job_locations.job_post_id = job_posts.id
        AND FIND_IN_SET(job_post_job_locations.remote_location_id, :P9)
    )
)
AND (
    (:P1 IS NULL OR LENGTH(:P1) = 0)
    OR EXISTS (
        SELECT 1
        FROM job_post_job_post_tech
        WHERE job_post_job_post_tech.job_post_id = job_posts.id
        AND FIND_IN_SET(job_post_job_post_tech.tech, :P1)
    )
)
AND (
    (:P2 IS NULL OR LENGTH(:P2) = 0)
    OR EXISTS (
        SELECT 1
        FROM job_posts
        INNER JOIN companies ON companies.id = job_posts.company_id
        WHERE job_posts.id = job_posts.id
        AND FIND_IN_SET(companies.company_staff_size_ref, :P2)
    )
)

AND (
    (:P4 IS NULL OR LENGTH(:P4) = 0)
    OR EXISTS (
        SELECT 1
        FROM job_post_job_post_cat_related
        WHERE job_post_job_post_cat_related.job_post_id = job_posts.id
        AND FIND_IN_SET(job_post_job_post_cat_related.job_sub_category, :P4)
    )
)
AND (
    (:P6 IS NULL OR LENGTH(:P6) = 0)
    OR EXISTS (
        SELECT 1
        FROM job_posts
        INNER JOIN companies ON companies.id = job_posts.company_id
        INNER JOIN company_sectorTags_join ON company_sectorTags_join.company_id = companies.id
        WHERE job_posts.id = job_posts.id
        AND FIND_IN_SET(company_sectorTags_join.sector_tag_id, :P6)
    )
)
AND (
    (:P3 IS NULL OR LENGTH(:P3) = 0)
    OR EXISTS (
        SELECT 1
        FROM job_post_job_level
        WHERE job_post_job_level.job_post_id = job_posts.id
        AND FIND_IN_SET(job_post_job_level.level, :P3)
    )
)
AND (
    (:P7 IS NULL)
    OR job_posts.salary_low IS NULL
    OR (:P7 <= job_posts.salary_low)
)
;
3 Likes