0

There is a table with 50 columns and they all contain numbers from 1 to 99. If I wanted to search, e.g. 8,36,52 no matter where they are, as long as they are in the same tuple, would I do it? I'm stuck because if I specify the column, I limit the search. Please, any help is welcome!

Dale K
  • 25,246
  • 15
  • 42
  • 71
  • 2
    `where (c1=8 or c2=8 or c3=8...) and (c1=36 or c2=36 or c3=36...) and (c1=52 or c2=52 or c3=52...)`? – GSerg Aug 03 '21 at 21:28
  • 4
    Basically if you’ve got 50 columns of numbers so indistinguishable that it makes sense to search them collectively for matching numbers, irrespective of their assigned columns, then you’ve got a bad (non-relational) data design. You can sometimes justify searching across columns for text substrings, but rarely for numbers: they should’ve been designed to all be in one column in the first place. – RBarryYoung Aug 03 '21 at 21:32

2 Answers2

0

This will dynamically UNPIVOT the row without having to use Dynamic SQL

Example or dbFiddle

Declare @Search varchar(50)='8,36,52';

with cte as (
 Select Distinct Value From string_split(@Search,',')
) 
Select A.* 
 From YourTable A
 Cross Apply (
                Select Hits =Count(Distinct B1.Value)
                 From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper )) B1
                 Join cte B2 on B1.Value=B2.Value
             ) B
 Where Hits = ( select count(*) from cte )
John Cappelletti
  • 79,615
  • 7
  • 44
  • 66
0

Here is another method based on XML/XQuery.

It is using XQuery's Quantified Expressions.

Quantified Expressions (XQuery)

Given two sequences, if every item in the first sequence has a match in the second sequence, the returned value is True. Exactly what we need.

The XML inside the CTE looks like this for each row:

<root>
  <source>
    <r>8</r>
    <r>36</r>
    <r>52</r>
  </source>
  <target>
    <ID>1</ID>
    <Col1>0</Col1>
    <Col2>15</Col2>
    <Col3>45</Col3>
    <Col4>7</Col4>
    <Col5>88</Col5>
    <Col6>22</Col6>
  </target>
</root>

SQL

-- DDL and data population, start
DECLARE @tbl TABLE
(
    ID INT IDENTITY PRIMARY KEY,
    [Col1] INT,
    [Col2] INT,
    [Col3] INT,
    [Col4] INT,
    [Col5] INT,
    [Col6] INT
);
INSERT INTO @tbl
VALUES
(0, 15, 45, 7, 88, 22),
(1, 36, 8, 7, 14, 52),
(32, 36, 36, 1, 1, 1); -- Duplicate Values
-- DDL and data population, end

DECLARE @Search VARCHAR(50) = '8,36,52'
    , @separator CHAR(1) = ',';

;WITH rs AS
(
    SELECT * 
    , TRY_CAST('<root>' + 
       '<source><r><![CDATA[' + REPLACE(@Search, @separator, ']]></r><r><![CDATA[') + 
          ']]></r></source>' + 
       (SELECT * FROM @tbl AS c 
       WHERE p.ID = c.ID
       FOR XML PATH(''), ROOT('target')) + 
       '</root>' AS XML)
          .query('every $x in /root/source/r/text()
                satisfies ($x = (/root/target/*[local-name()!="ID"]/text()))')
          .value('text()[1]', 'bit') result
    FROM @tbl AS p
)
SELECT * FROM rs
WHERE rs.result = 1;
Yitzhak Khabinsky
  • 18,471
  • 2
  • 15
  • 21