I have a 20 Column in a Table Col1, Col2, Col3 .... Col20. RowNo column is a primary column, Col1 to Col20 is a not null int column
in each Column has unique data for single row(means Col1 has 10 so in Col2 to Col20 values is not repeat). table has approx 100000 records.
i have a 10 values like 18, 3, 15, 16, 11, 5, 41, 61, 43, 80 i want to search each records in all 20 column.
select only those rows which has all 10 values in col1 to col20
For Ex. 18 can be match in col1 to col20
as per the below data return 4th row result may be return more then one row
SELECT * FROM
yourTable
WHERE
CASE WHEN 18 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 3 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 15 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 16 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 11 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 5 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 41 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 61 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 43 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
+ CASE WHEN 80 IN (col1, col2, col3, ...col20) THEN 1 ELSE 0 END
= 10
An Alternative: Copy your data into a query-friendly table.
The table:
CREATE TABLE [dbo].[tblX](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ColN] [int] NULL,
[Value] [int] NULL,
[RowNo] [int] NULL
);
Copy data over:
INSERT INTO tblX(RowNo, ColN, Value)
SELECT RowNo, 1, Col1 FROM tblCols;
INSERT INTO tblX(RowNo, ColN, Value)
SELECT RowNo, 2, Col2 FROM tblCols;
INSERT INTO tblX(RowNo, ColN, Value)
SELECT RowNo, 3, Col3 FROM tblCols;
INSERT INTO tblX(RowNo, ColN, Value)
...
INSERT INTO tblX(RowNo, ColN, Value)
SELECT RowNo, 20, Col20 FROM tblCols;
The query:
SELECT
*
FROM
tblX
WHERE RowNo IN
(
SELECT
RowNo
FROM
tblX
WHERE
Value IN (18, 3, 15, 16, 11, 5, 41, 61, 43, 80)
GROUP BY RowNo
HAVING COUNT(*) = 10 -- the number of numbers above
)
ORDER BY RowNo, ColN
you first get the filter value as a comma separated, and then using below function get it in a table in different rows
CREATE FUNCTION [dbo].[Split]
(
@String VARCHAR(200),
@Delimiter VARCHAR(5)
)
RETURNS @SplittedValues TABLE
(
OccurenceId SMALLINT IDENTITY(1,1),
SplitValue VARCHAR(200)
)
AS
BEGIN
DECLARE @SplitLength INT
WHILE LEN(@String) > 0
BEGIN
SELECT @SplitLength = (CASE CHARINDEX(@Delimiter,@String) WHEN 0 THEN
LEN(@String) ELSE CHARINDEX(@Delimiter,@String) -1 END)
INSERT INTO @SplittedValues
SELECT SUBSTRING(@String,1,@SplitLength)
SELECT @String = (CASE (LEN(@String) - @SplitLength) WHEN 0 THEN ''
ELSE RIGHT(@String, LEN(@String) - @SplitLength - 1) END)
END
RETURN
now declare a cusor for this table to get one by one value
now in side this cursor using
SELECT s.name SchemaName, t.name TableName, c.name ColumnName
FROM sys.columns c INNER JOIN
sys.tables t ON c.object_id = t.object_id INNER JOIN
sys.schemas s ON t.schema_id = s.schema_id
;
get all the columns of one row in different rows and run loop of it and check with it filter value, basically inside above cursor you have to run another cursor
its ugly, lengthy , but better than nothing :-)
before your answer i am use below function which is return me a match count and get where count = 10
Create FUNCTION [dbo].[MatchRows]
(
@id int,
@No1 int,
@No2 int,
@No3 int,
@No4 int,
@No5 int,
@No6 int,
@No7 int,
@No8 int,
@No9 int,
@No10 int
)
RETURNS bit
AS
BEGIN
Declare @ReturnVal bit = 0;
Declare @Allvalue varchar(max);
Declare @CntMatch int;
SELECT @Allvalue = ',' + Convert(varchar(3),No1)+ ',' +
Convert(varchar(3),No2)+ ',' +
Convert(varchar(3),No3)+ ',' +
Convert(varchar(3),No4)+ ',' +
Convert(varchar(3),No5)+ ',' +
Convert(varchar(3),No6)+ ',' +
Convert(varchar(3),No7)+ ',' +
Convert(varchar(3),No8)+ ',' +
Convert(varchar(3),No9)+ ',' +
Convert(varchar(3),No10)+ ',' +
Convert(varchar(3),No11)+ ',' +
Convert(varchar(3),No12)+ ',' +
Convert(varchar(3),No13)+ ',' +
Convert(varchar(3),No14)+ ',' +
Convert(varchar(3),No15)+ ',' +
Convert(varchar(3),No16)+ ',' +
Convert(varchar(3),No17)+ ',' +
Convert(varchar(3),No18)+ ',' +
Convert(varchar(3),No19)+ ',' +
Convert(varchar(3),No20)+ ','
FROM DrawFinalResult
WHERE ID = @ID;
SET @CntMatch = 0;
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No1) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No2) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No3) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No4) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No5) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No6) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No7) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No8) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No9) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Select @CntMatch += (CASE WHEN CHARINDEX(','+ Convert (varchar(3),@No10) +',',@Allvalue) > 0 THEN 1 Else 0 END);
Set @ReturnVal = (CASE WHEN @CntMatch = 10 THEN 1 ELSE 0 END);
RETURN @ReturnVal
END
You also can use unpivot
to reduce typing col1, col2, ..., colN
(especially if it will differ in future). You can try smth like this:
create table Unpivoted (RoNo int, Value int primary key)
insert Unpivoted
select
upvt.RoNo, upvt.Value
from (
select * from YourTable
) src
unpivot (
Value for ColNo in (
col1, col2, col3, col4, col5,
col6, col7, col8, col9, col10 -- etc.
)
) upvt
select
*
from YourTable yt
join (
select
RoNo
from Unpivoted
where
Value in (
18, 3, -- etc. N values at all
)
group by
RoNo
having
count(*) = N
) x on
yt.RoNo = x.RoNo
drop table Unpivoted
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.