Home > database >  how to return missing row based on column, where other values match in MSSQL
how to return missing row based on column, where other values match in MSSQL

Time:06-03

I don't even know how to ask this so I can google, so my apologies in advance. I have a SQL table where it looks something like this

col1 col2 col3
a    1    name1
a    2    name1
a    3    name1
a    4    name1
b    1    name1
b    2    name1
b    3    name1

If you notice, there are 4 rows for col1=a for each col2 value[1-4]. There is NOT, however, a record where col1=b and col2=4.

With grouping and count<4 I can return rows that exist, but how can I return something like 'b,4,name1' for a row (my missing record)

SELECT * FROM
(
SELECT T.COL1, T.COL3, COUNT(T.COL2) COL2_COUNT, STRING_AGG(T.COL2,',') COL2_LIST
FROM
(
SELECT F.COL1, F.COL3, F.COL2 FROM TBL F 
) T
GROUP BY T.COL1, T.COL3
) J WHERE J.COL2_COUNT < 4

CodePudding user response:

All unique combinations of Col1&Col3 is to have a row for each unique col2 in the table:

select UCol1_2.col1, UCol2.col2, UCol1_2.Col3
from (
      select distinct col2
      from yourtable
     ) UCol2
     cross join
     (
      select distinct col1, col3
      from yourtable
     ) UCol1_2

     left join
     yourtable a
     on a.col2=UCol2.col2
     and a.Col1=UCol1_2.Col1
     and a.Col3=UCol1_2.Col3
where a.col2 is null

CodePudding user response:

I noticed after doing this you're looking for MSSQL. If the question becomes live again I'll put in the MSSQL version.

The basic idea is to create a cross join and then filter out what is missing by testing for filter.col1 is null.

Schema (MySQL v5.7)

    CREATE TABLE stack_overflow_72485200
        (`col1` varchar(1), `col2` int, `col3` varchar(5))
    ;
        
    INSERT INTO stack_overflow_72485200
        (`col1`, `col2`, `col3`)
    VALUES
        ('a', 1, 'name1'),
        ('a', 2, 'name1'),
        ('a', 3, 'name1'),
        ('a', 4, 'name1'),
        ('b', 1, 'name1'),
        ('b', 2, 'name1'),
        ('b', 3, 'name1')
    ;

Query #1


    select candidate_base.* from (
        select candidate.col1, base.col2, base.col3 from (
        select col1 
        from stack_overflow_72485200 missing
        group by col1
      ) candidate, 
      (
        select col2, col3 
        from stack_overflow_72485200 base
        group by col2, col3 ) base 
      ) candidate_base
      left join stack_overflow_72485200 filter
      on candidate_base.col1 = filter.col1
      and candidate_base.col2 = filter.col2
      and candidate_base.col3 = filter.col3
      where filter.col1 is null;
      
col1 col2 col3
b 4 name1

View on DB Fiddle

  • Related