mysqljoinfilter

mysql join to record first one which is not matched before


i would like to know is it possible to join 2 tables with a condition like delist the item when it has a match for once.

Let me explain,

take a look at -- > https://dbfiddle.uk/yje6VfFz

Table name : material (which items will be produced)

refcode bomlevel nextbomlevel
pizza 0 0
dough 1 0
cheese 2 0
cheese 3 0
flour 4 1
water 5 1

Table name : components (which items will be used for production)

refcode bomlevel item
dough 0 10
cheese 0 20
cheese 0 30
flour 1 40
water 1 50
milk 2 60
milk 3 70
wheat 4 80
hidrogen 5 90
oxygen 5 100

when i run the query below

SELECT 
    c.*, m.bomlevel BomLevelOfComponent
FROM
    components c
        LEFT JOIN
    materials m ON c.bomlevel = m.nextbomlevel
        AND c.refcode = m.refcode

result table is;

refcode bomlevel item BomLevelOfComponent
dough 0 10 1
cheese 0 20 3
cheese 0 20 2
cheese 0 30 3
cheese 0 30 2
flour 1 40 4
water 1 50 5
milk 2 60 null
milk 3 70 null
wheat 4 80 null
hidrogen 5 90 null
oxygen 5 100 null

now back to question...

i would like to get cheese rows on the result table 2 times as below (not 4 times). by the way, this is not my structure, so i can not change data. i'm looking for a specified query to get the result what i need at the end.

This is my target result table

refcode bomlevel item BomLevelOfComponent
dough 0 10 1
cheese 0 20 2
cheese 0 30 3
flour 1 40 4
water 1 50 5
milk 2 60 null
milk 3 70 null
wheat 4 80 null
hidrogen 5 90 null
oxygen 5 100 null

i'm trying to join 2 mysql tables but when a record match, it will be delisted not to match again.


Solution

  • This is MS Copilot's answer and it worked.

    Copilot : Alright, so the goal is to match each component with its corresponding material, making sure no component is left out, and each material is used only once. Here's a refined approach:

    WITH CTE AS (
        SELECT *,
            ROW_NUMBER() OVER (PARTITION BY refcode ORDER BY bomlevel) AS rn
        FROM materials
    )
    SELECT 
        c.refcode,
        c.bomlevel,
        c.item,
        m.bomlevel AS BomLevelOfComponent
    FROM 
        components c
    LEFT JOIN CTE m 
    ON c.refcode = m.refcode 
    AND c.bomlevel = m.nextbomlevel 
    AND m.rn = (
        SELECT COUNT(*)
        FROM components sub_c 
        WHERE sub_c.refcode = c.refcode 
        AND sub_c.bomlevel = c.bomlevel 
        AND sub_c.item <= c.item
    )
    ORDER BY c.item;
    

    Copilot : This ensures each cheese item gets matched uniquely with the materials available. Both item 20 and item 30 should be included. Let me know if this finally does the trick.

    Me : yeah it works like a charm

    Copilot : Awesome! Glad we finally nailed it. Persistence pays off, right? Anything else you need help with, or are we ready to call it a win?

    Me : case closed

    Copilot : High five! Glad we cracked it. If any more mysteries come your way, you know where to find me. For now, take care!