我有一个包含一些值和大量过滤器的SQL表
ID | Name | Filter1 | Filter2 | Filter3 | Filter4 ... and so on...
现在,过滤器已设置为int,我按如下方式运行查询以获取所需数据
select Name
from tblABC
where Filter1=1 and Filter2 = 7 and Filter3 = 33 ... and so on...'
我的问题是我想要一个过滤列来保存多个数字。例如: - 第3行将在Filter1单元格中包含数字8和13,因此当我运行8或13的查询时,我得到相同的结果。 即我希望以下两个查询返回相同的结果。
select... where Filter1=8
select... where Filter1=13
如何做到这一点?我尝试将Filter列转换为nvarchar并输入数据为.8.13。在哪里'。'在哪里用作分隔符。在此之后,运行查询'select ...其中Filter1 LIKE'%。8.。%'对我有用..但是有12个Filter列,当这样的字符串搜索大量运行时,不会使查询变慢。什么是更有效的方法呢?
我正在使用Microsoft SQL 2014
答案 0 :(得分:3)
一种更有效的方式,嗯。从过滤器中分离 tblABC 将是我建议的方法,即使它不是最有效的方式来弥补它的维护(并且它肯定比使用通配符更有效) )。
tblABC ID Name
1 Somename
2 Othername
tblABCFilter ID AbcID Filter
1 1 8
2 1 13
3 1 33
4 2 5
如何查询此数据取决于您当前所需的输出。一种方法是使用以下内容:
SELECT tblABC.Name FROM tblABC
INNER JOIN tblABCFilter ON tblABC.ID = tblABCFilter.AbcID
WHERE tblABCFilter.Filter = 33
这将使用 33 的过滤器返回所有名称。
如果要查询多个过滤器:
SELECT tblABC.Name FROM tblABC
INNER JOIN tblABCFilter ON tblABC.ID = tblABCFilter.AbcID
WHERE tblABCFilter.Filter IN (33,7)
这将在 33 或 7 中使用过滤器返回所有名称。
我创建了一个小example fiddle.
答案 1 :(得分:1)
我要发布我使用的解决方案。我使用拆分功能(整个互联网上有很多SQL Server拆分功能)
你可以举例如
CREATE FUNCTION [dbo].[SplitString]
(
@List NVARCHAR(MAX),
@Delim VARCHAR(255)
)
RETURNS TABLE
AS
RETURN ( SELECT [Value] FROM
(
SELECT
[Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
FROM sys.all_objects) AS x
WHERE Number <= LEN(@List)
AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim
) AS y
);
并像这样运行您的查询
select Name
from tblABC
where Filter1 IN (
SELECT * FROM SplitString(@DatatoFilter,',') and
Filter2 (IN (
SELECT * FROM SplitString(@DatatoFilter,',') and
..so on.
如果你有成千上万的记录,它可能表现不佳。但它应该工作。
我个人的aproch将是一个存储过程和临时表。创建一个临时表,其中包含要用作过滤器的所有值
SELECT *
INTO #Filter1
FROM SplitString(@DatatoFilter,',')
SELECT *
INTO #Filter2
FROM SplitString(@DatatoFilter,',')
然后是最终选择
SELECT * FROM yourtable
WHERE Filter1 IN (SELECT DISTINCT Part FROM #Filter1) and
Filter2 IN (SELECT DISTINCT Part FROM #Filter2)
我认为它与第一个查询没什么大不同,但它更容易阅读。
答案 2 :(得分:0)
您可以尝试的另一种解决方案是将列转换为XML
。它比将列转换为VARCHAR
更好。您可以使用.exist
仅获取符合条件的记录。这样的事情。
DECLARE @table1 TABLE
(
[ID] int, [Name] varchar(9),Filter1 XML
)
INSERT INTO @table1
([ID], [Name],Filter1)
VALUES
(1, 'Somename','<Filter>8</Filter>'),
(2, 'Othername','<Filter>8</Filter><Filter>13</Filter>'),
(3, 'Thirdname','<Filter>25</Filter>')
DECLARE @FilterValue INT = 8
SELECT Filter1.query('/Filter'),*
FROM @table1
WHERE Filter1.exist('/Filter[. = sql:variable("@FilterValue")]') = 1
修改强>
您甚至可以使用XML
列来存储所有12个过滤器。所以这个过滤器xml列存储了所有过滤器及其多个值。
DECLARE @table1 TABLE
(
[ID] int, [Name] varchar(9),Filter XML
)
INSERT INTO @table1
([ID], [Name],Filter)
VALUES
(1, 'Somename','<Filter ID = "1"><FilterVal>8</FilterVal></Filter><Filter ID = "2"><FilterVal>3</FilterVal><FilterVal>12</FilterVal></Filter>'),
(2, 'Othername','<Filter ID = "1"><FilterVal>8</FilterVal><FilterVal>13</FilterVal></Filter><Filter ID = "2"><FilterVal>8</FilterVal><FilterVal>13</FilterVal></Filter>'),
(3, 'Thirdname','<Filter ID = "2"><FilterVal>12</FilterVal><FilterVal>25</FilterVal></Filter><Filter ID = "3"><FilterVal>33</FilterVal></Filter>')
DECLARE @Filter1Value INT = 8
DECLARE @Filter2Value INT = 12
SELECT *
FROM @table1
WHERE Filter.exist('/Filter[@ID = 1]/FilterVal[. = sql:variable("@Filter1Value")]') = 1
AND Filter.exist('/Filter[@ID = 2]/FilterVal[. = sql:variable("@Filter2Value")]') = 1