基于变量:SQL Query从一列中获取多个值的数据或从该列获取所有值

时间:2016-01-22 07:01:33

标签: sql-server

问题陈述:

  1. @a只有一个单词(例如'name1')或逗号分隔的字符串(示例'name1,name2,name3')时,查询应返回name1 and name2 and name3的员工的经理姓名
  2. @a有一个空字符串,然后返回emp_master表中所有员工的经理姓名
  3. 我已经定义了一个传递变量的存储过程。

    此变量可以是逗号分隔的字符串,单个字或空字符串。

    如果字符串是逗号分隔的,那么我拆分该字符串并根据split语句的返回表获取值 其他 我使用普通子查询

    得到非逗号分隔数据的相关值

    我试图通过以下方式实现这一目标

    Declare @a varchar(50)= ''
    select emp.Name from 
    emp_master emp
    where 
    (LEN(@a)=0 AND emp.Name in
     (
            SELECT DISTINCT [Name] FROM 
            [dbo].[Emp_Master] WHERE [EmpId] IN 
            (
                SELECT 
                DISTINCT [MGR_ID] 
                FROM [dbo].[Emp_Master]
            )
        )
    )
    OR 
    emp.Name in (Select * from [dbo].[SplitString](@a, ',')) 
    

    以上样本的详细信息:

    1. [dbo]。[SplitString] - 自定义编写函数:返回拆分值表。所以

      从[dbo] .SplitString

    2. 中选择*

      将返回

      SplitTable
      ----------
      name1
      name2
      name3
      

      Select * from [dbo].[SplitString](',','name1')
      

      将返回

      SplitTable
      ----------
      name1
      
      1. [dbo]。[Emp_Master]包含所有员工的数据
      2. [MGR_ID]是具有员工经理的employeeID的列
      3. @a是输入变量
      4. 数据库是MS SQL 2008
      5. 我当前的解决方案(上面的疯狂查询)解决了我的目的,但速度非常慢,为问题获得优化且更快的工作解决方案会很有帮助

        • Emp_master表有400 000行,30列
        • 该表中有18 000名经理

2 个答案:

答案 0 :(得分:0)

CREATE NONCLUSTERED INDEX ix ON dbo.Emp_Master ([MGR_ID])
GO 

DECLARE @a VARCHAR(50) = '' 

DECLARE @t TABLE (val VARCHAR(50) PRIMARY KEY WITH(IGNORE_DUP_KEY=ON))
INSERT INTO @t
SELECT item = t.c.value('.', 'INT') 
FROM (
    SELECT txml = CAST('<r>' + REPLACE(@a, ',', '</r><r>') + '</r>' AS XML)
) r
CROSS APPLY txml.nodes('/r') t(c)

SELECT /*DISTINCT*/ [Name]
FROM dbo.Emp_Master e1
WHERE (
            @a = ''
        AND
            e1.[EmpId] IN (SELECT DISTINCT MGR_ID FROM dbo.Emp_Master)
    )
    OR (
            @a != ''
        AND
            e.Name IN (SELECT * FROM @t)
       )
OPTION(RECOMPILE)

答案 1 :(得分:0)

尝试

CREATE NONCLUSTERED INDEX IX_MGR_ID_Emp_Master   ON dbo.Emp_Master ([MGR_ID])
GO 




Create Procedure searchname (@a varchar(255))
as
IF (@a = '')
BEGIN
EXEC Searchname1 @a
END
ELSE
BEGIN
EXEC Searchname2 @a 
END

GO

Create Procedure Searchname1 (@a varchar(255))
AS
 SELECT DISTINCT [Name] FROM 
        [dbo].[Emp_Master] m1 WHERE 
        exists


        (
            SELECT 
            *  
            FROM [dbo].[Emp_Master] m2
            WHERE 
            m1.[EmpId]= m2.[MGR_ID] 
            )

GO

Create Procedure Searchname2 (@a varchar(max)) 
AS




Select @a = ' SELECT  '''+replace( @a,',','''  Union ALL SELECT   ''')+'  '''

Create table #names (name varchar(255))
insert into #names
EXEC ( @a )


select emp.Name from 
emp_master emp
WHERE
emp.Name in( Select name FRom #names)
option (recompile)
  

如果您已经在应用程序级别处理 SQL INJECTION   THEN

ALTER procedure [dbo].[Searchname2] (@a varchar(max)) 
AS





select  @a  = ''''+replace ( @a,',',''',''')+''''
DECLARE @sql NVARCHAR(MAX) = N'
select distinct emp.Name from 
emp_master emp
WHERE
emp.Name in( '+@a+')'


EXEC (@sql)