2016-01-22 55 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個用戶在同一頁面上工作時的數據庫負載,不會嗎? –

相關問題