Home > OS >  reference code to fill one of those two table in condition
reference code to fill one of those two table in condition

Time:02-04

I am not sure how to get the right script

To get the reference code detail, one of those tables 'car_col' has to fill in not duplicate results from the other second tables 'car_cat', if 'car_col' doesn't have then 'car_cat' fill in

select 
a. customer_id ,
a. car_code ,
b. description as code_desc ,
a. price

from product a

left join (select * from reference_codes where domain in ('car_col', 'car_cat') ) b
on a. car_code   =  b. code

output result;

customer_ID code description
123 12 blue
123 23 black
345 45 red
345 45 red
678 67 green
678 24 yellow
908 45 red
908 70 purple

as you can see customer 345 has double row code 45 red

REFERENCE TABLES below;

select * from reference_codes where domain = 'car_col'

DOMAIN CODE DESCRIPTION
car_col 12 blue
car_col 23 black
car_col 45 red
car_col 67 green

select * from reference_codes where domain = 'car_cat'

DOMAIN CODE DESCRIPTION
car_cat 24 yellow
car_cat 45 red
car_cat 70 purple
car_cat 90 row

I want output result

customer_ID code description
123 12 blue
123 23 black
345 45 red
678 67 green
678 24 yellow
908 45 red
908 70 purple

I am using ORACLE SQL

thank you

CodePudding user response:

Hard to give a concrete answer with really seeing all the data or the model, but I'm interpreting your requirement as:

"If I can't find a join on a customer to CAR_COL then fall back to using CAR_CAT"

Taking your existing code, we can add a column to "prioritise" the data, eg

select *
from (
    select 
      a.customer_id ,
      a.car_code ,
      b.description as code_desc ,
      a.price,
      row_number() over ( partition by customer_id, car_code
         order by case when domain = 'car_col' then 1 else 2 end ) as rating
    from product a
    left join (select * from reference_codes 
               where domain in ('car_col', 'car_cat') ) b
    on a. car_code   =  b. code
)
where rating = 1

CodePudding user response:

If your sample data is something like here:

WITH
    reference_codes (DOMAIN, CAR_CODE, DESCRIPTION) AS
        (
            Select  'car_col',  12, 'blue'      From  Dual Union All
            Select  'car_col',  23, 'black'     From  Dual Union All
            Select  'car_col',  45, 'red'       From  Dual Union All
            Select  'car_col',  67, 'green'     From  Dual Union All
                    
            Select  'car_cat',  24, 'yellow'    From  Dual Union All
            Select  'car_cat',  45, 'red'       From  Dual Union All
            Select  'car_cat',  70, 'purple'    From  Dual Union All
            Select  'car_cat',  90, 'row'       From  Dual 
        ),
    product (CUSTOMER_ID, CODE, PRICE) AS
        (
            Select 123, 12, 100     From  Dual Union All
            Select 123, 23, 100     From  Dual Union All
            Select 345, 45, 120     From  Dual Union All
            Select 345, 45, 120     From  Dual Union All
            Select 678, 67, 110     From  Dual Union All
            Select 678, 24, 110     From  Dual Union All
            Select 908, 45, 130     From  Dual Union All
            Select 908, 70, 130     From  Dual 
        )

... then with your query the result is as you showed above. There is column PRICE selected but we can't see the values in your question, though.

CUSTOMER_ID       CODE CODE_DESC      PRICE
----------- ---------- --------- ----------
        123         12 blue             100 
        123         23 black            100 
        345         45 red              120 -- one row less if 'car_col' is missing
        345         45 red              120 
        345         45 red              120 
        345         45 red              120 
        678         24 yellow           110 
        678         67 green            110 
        908         70 purple           130 
        908         45 red              130 
        908         45 red              130

To get your expected result (if there are no different prices) you could just add DISTINCT keyword to get what you want:

Select DISTINCT
... ... ... your query
CUSTOMER_ID       CODE CODE_DESC      PRICE
----------- ---------- --------- ----------
        123         12 blue             100 
        123         23 black            100 
        345         45 red              120 
        678         24 yellow           110 
        678         67 green            110 
        908         45 red              130 
        908         70 purple           130 

... and if there are different prices than you could use aggregation with group by like below

Select    
    a.CUSTOMER_ID ,
    a.CODE ,
    b.DESCRIPTION "CODE_DESC",
    AVG(a.PRICE) "AVG_PRICE"
From
    product a
Left Join 
    ( Select * From reference_codes Where DOMAIN IN('car_col', 'car_cat') ) b
    ON(a.CODE =  b.CAR_CODE)    
Group By
    a.CUSTOMER_ID ,
    a.CODE ,
    b.DESCRIPTION
Order By 
    a.CUSTOMER_ID
CUSTOMER_ID       CODE CODE_DESC  AVG_PRICE
----------- ---------- --------- ----------
        123         12 blue             100 
        123         23 black            100 
        345         45 red              120 
        678         24 yellow           110 
        678         67 green            110 
        908         45 red              130 
        908         70 purple           130

Your query adjusted (depending on PRICE) either by DISTINCT or aggregation will work ok even when 'car_col' is missing:

WITH
    reference_codes (DOMAIN, CAR_CODE, DESCRIPTION) AS
        (
            Select  'car_col',  12, 'blue'      From  Dual Union All
            Select  'car_col',  23, 'black'     From  Dual Union All
--Select    'car_col',  45, 'red'       From  Dual Union All
            Select  'car_col',  67, 'green'     From  Dual Union All
                    
            Select  'car_cat',  24, 'yellow'    From  Dual Union All
            Select  'car_cat',  45, 'red'       From  Dual Union All
            Select  'car_cat',  70, 'purple'    From  Dual Union All
            Select  'car_cat',  90, 'row'       From  Dual 

CodePudding user response:

To get the desired output, you can use the CASE statement and ROW_NUMBER function in your SQL query as below:

select 
a.customer_id,
a.car_code,
case 
  when row_number() over (partition by a.customer_id, a.car_code order by b.domain = 'car_col') = 1 
  then b.description 
end as code_desc,
a.price

from product a

left join (select * from reference_codes where domain in ('car_col', 'car_cat') ) b
on a.car_code   =  b.code

group by a.customer_id, a.car_code, code_desc, a.price

The CASE statement checks if the ROW_NUMBER function is equal to 1, and returns the description only if it is. The ROW_NUMBER function is used to assign a unique number to each row within a partition (in this case, partitioned by customer_id and car_code) and ordered by the domain being equal to 'car_col'. By doing this, we ensure that the first row for each customer_id and car_code combination is the one from the 'car_col' table. The GROUP BY clause is used to aggregate the rows with the same customer_id, car_code, code_desc, and price.

  • Related