2016-01-22 54 views
1

问题陈述得到的所有值:基于一个变量:SQL查询来从一列取多个值的数据或从该列

  1. @a具有单个字(实施例'name1')OR逗号分隔的字符串(例'name1,name2,name3'),则查询应与​​name1 and name2 and name3
  2. 返回雇员的经理名称时@a有那么一个空字符串在emp_master表返回所有员工的经理姓名

我已经定义了一个存储过程,我传递一个变量。

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

如果字符串是逗号,然后分开后,我拆分字符串,并基于分裂声明 其他 的返回表我得到的非逗号的相关值获取值使用正常的子查询

我曾尝试分离数据通过以下方式实现这一目标对上述样品

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] - 自定义书写功能:返回分割值表。所以

    SELECT * FROM [DBO] .SplitString

将返回

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

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

将返回

SplitTable 
---------- 
name1 
  1. [dbo]。[Emp_Master]包含数据的所有员工
  2. [MGR_ID]是具有雇员管理者
  3. @a的雇员ID列是输入变量
  4. 数据库是MS SQL 2008

我目前的解决方案(上述疯狂的查询)解决了我的目的,但它是非常缓慢的,这将有助于获取问题

  • Emp_master表有40万行,30列的优化和更快的工作解决方案
  • 有18名000经理在该表
+0

shaik你的代码是可能的原因有三慢: (1)参数嗅探 (2)标量功能在哪里条件 (3)不良指数 –

+0

当@a用逗号分隔字符串时,它可能有多长? –

回答

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) 
+0

MGR_ID是一个varchar类型,因此只是将INT更改为NVARCHAR(MAX),并将时间从7秒缩短为1秒,对于我的任务而言足够快。 使用XML类型真是太神奇了,保存了很多时间 谢谢@Devart你是一个天才。 –

+0

另外,请阅读有关字符串拆分和参数嗅探... – Devart

+0

@Abuzar谢赫欢迎;) – Devart

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('[email protected]+')' 


EXEC (@sql) 
+0

感谢您的帮助。 创建临时表可能会增加10000个用户在同一页面上工作时的数据库负载,不会吗? –

相关问题