Skip to content
Advertisement

Include all selected types, filter out duplicate where primaryType takes precedence

What I’m trying to accomplish is select from a table and return all the records where the Type matches one of the parameter types. Remove duplicates with the primaryType being the record of choice if found, if not then a single record from one of the other type arguments. The order doesn’t matter for the other types although it would be nice (can pick @secondType or @thirdType). This is a POC project so if I need to add or change things to make it easier/faster I’m open to ideas!

NOTE: UUID and PARTID are alphanumeric. 
DECLARE  @primaryType varchar(32) = 'diamond';
DECLARE  @secondType varchar(32)  = 'gold';
DECLARE  @thirdType varchar(32)   = 'nickel';


SettingName     Type        PARTID  UUID
----------------------------------------
Alpha           diamond     123     123     <== Returned because the primaryType takes precedence 
Alpha - g       gold        123     321     <== Not returned because it would be a duplicate, primaryType wins
Charlie         diamond     456     456     <== Returned; no duplicate partid and is in type list.
Delta - c       copper      789     789     <== Not returned becuase it's not in type list
Echo - g        gold        987     987     <== Returned because no duplicate partid and is in type list

Desired result…

Alpha           diamond     123     123     <== Returned because the primaryType takes precedence 
Charlie         diamond     456     456     <== Returned no duplicate partid and is in type list.
Echo - g        gold        987     987     <== Returned because no duplicate partid and is in type list

I’ve tried something like the code below as well as other code but just can’t seem to nail it down.

 SELECT * from
    ( SELECT SettingName, Type, PARTID, UUID
            ,row_number() over (partition by PARTID order by Type ) idx
      FROM Settings
      WHERE
        (Type = @primaryType OR Type = @secondType OR Type = @thirdType) 
    ) a where idx = 1 

Where the code above gets hung up is the order by Type can return the wrong result because the @primaryType may be further down the list when sorted. Which would return @secondType or @thirdType depending on the sorted result.

Advertisement

Answer

You are almost there, just use the @Type values in the over(order by) clause to create custom ordering/precedence.

declare @t table
(
id int identity,
SettingName varchar(50),
Type varchar(50),
PARTID varchar(50),
UUID varchar(50)
);

insert into @t(SettingName, Type, PARTID, UUID)
values
('Alpha', 'diamond', '123', '123'),   --<== Returned because the primaryType takes precedence 
('Alpha - g', 'gold', '123', '321'),   --<== Not returned because it would be a duplicate, primaryType wins
('Charlie', 'diamond', '456', '456'),  --<== Returned; no duplicate partid and is in type list.
('Delta - c', 'copper', '789', '789'), -- <== Not returned becuase it's not in type list
('Echo - g', 'gold', '987', '987'); 

DECLARE  @primaryType varchar(32) = 'diamond';
DECLARE  @secondType varchar(32)  = 'gold';
DECLARE  @thirdType varchar(32)   = 'nickel';


select * 
from
(
    select *, 
        row_number() over(partition by PARTID order by case Type when  @primaryType then 1 when @secondType then 2 when @thirdType then 3 else 4 end, len(Type), id /*id as final tie-breaker*/) as rownum
    from @t
    where Type in (@primaryType, @secondType, @thirdType)
) as a
--where a.rownum = 1
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement