[英]Match Data in a Multiple Column
我在表Col1,Col2,Col3中有一個20列.... Col20。 RowNo列是主列,Col1到Col20是非null int列
在每列中具有單行的唯一數據(意味着Col1具有10,因此在Col2到Col20值中不重復)。 表有大約100000條記錄。
我有10個值,如18,3,15,16,11,5,41,61,43,80我想搜索所有20列中的每個記錄。
只選擇col1到col20中具有全部10個值的那些行
對於Ex。 18可以匹配col1到col20
根據以下數據返回第4行結果可能返回多於一行
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
替代方案:將數據復制到查詢友好的表中。
桌子:
CREATE TABLE [dbo].[tblX](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ColN] [int] NULL,
[Value] [int] NULL,
[RowNo] [int] NULL
);
復制數據:
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;
查詢:
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
首先以逗號分隔的方式獲取過濾器值,然后使用下面的函數將其放入不同行的表中
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
現在聲明這個表的cusor來逐個獲取值
現在在這個光標旁邊使用
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
;
獲取不同行中一行的所有列並運行它的循環並檢查它的過濾值,基本上在游標上方你必須運行另一個游標
它丑陋,冗長,但總比沒有好:-)
在你的答案之前,我使用下面的功能,它返回一個匹配計數,並得到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
您還可以使用unpivot
來減少輸入col1, col2, ..., colN
(特別是如果它將來會有所不同)。 你可以嘗試這樣的smth:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.