T-SQL从查找表获取值并在视图/存储过程中使用

时间:2019-06-27 10:31:05

标签: sql-server performance tsql

我无法通过搜索找到它,所以我想我问的不是正确的方法,因此欢迎您提供帮助。

我们有一个查询表:

Id   Name
------------------
1    "Test"
2    "New"
3    "InProgress"

表2:

StatusId  SomethingElse
  1   
  2

表1

ID  Other Other StatusId (Fkey to Table2) ...

然后我们有一个视图,该视图从多个表中选择,并且其中一列是CASE语句:

    SELECT * FROM Table1 t1 -- has million records

    CASE When t1.StatusId = 1 THEN (SELECT Name from LOOKUP table where ID = 1) END --'Test'
    CASE When t1.StatusId = 2 THEN (SELECT Name from LOOKUP table where ID = 2) END --'New'
CASE When t3.Date is not null THEN (SELECT Name from LOOKUP table where ID = 3) END --'In Progress'
-- AND ALSO the case look at other tables another 5-6 tables and there are conditions from there
INNER JOIN Table2 t2 on ...
INNER JOIN Table3 t3 on ...

如您所见,它们实际上是静态值。

我想一次将它们加载到变量中,例如

 @LookUp1 = SELECT [NAME] FROM LookUP WHERE Id = 1, 
 @LookUp2 = SELECT [NAME] FROM LookUP WHERE Id = 2 

,并将CASE语句中的select替换为:

When StatusId = 1 THEN @LookUp
When StatusId = 2 THEN @LookUp2

该视图遍历数百万条记录,并且从查找表中为每一行进行选择的过程确实很慢。

2 个答案:

答案 0 :(得分:3)

为什么不简单地使用联接?

SELECT <columns list from main table>, Lt.Name
FROM <main table> As Mt -- Do not use such aliases in real code!
JOIN <SecondaryTable> As St -- this represents your Table3
    ON <condition> 
[LEFT] JOIN <Lookup table> As Lt
    ON Mt.StatusId = Lt.Id
    OR (Lt.Id = 3 AND St.Date is not null)

当然,将<columns list from main table>替换为实际的列列表,将<main table>替换为主表的名称,依此类推。

取决于主表中StatusId列的可空性,以及该字段是否可为空,取决于在这种情况下您想要获得的内容(名称为空的行)或根本没有任何行)。

我整理了一个示范来向您展示我的意思。

创建并填充示例表(为您在以后的问题中保存此步骤)

CREATE TABLE LookUp (Id int, Name varchar(10));

INSERT INTO LookUp (Id, Name) VALUES
(1, 'Test'), (2, 'New'), (3, 'InProgress');


CREATE TABLE Table1 (Id int not null, StatusId int null);

INSERT INTO Table1(Id, StatusId)
SELECT n, CASE WHEN n % 3 = 0 THEN NULL ELSE (n % 3) END
FROM
(
    SELECT TOP 30 ROW_NUMBER() OVER(ORDER BY @@SPID) As n
    FROM sys.objects
) tally

CREATE TABLE Table3
(
    Id int not null,
    Date date null
)
INSERT INTO Table3 (Id, Date) 
SELECT Id,  CASE WHEN StatusId IS NULL AND Id % 4 = 0 THEN GetDate() END
FROM Table1

查询:

SELECT  Table1.Id, 
        Table1.StatusId, 
        Table3.Date,
        LookUp.Name
FROM Table1
JOIN Table3
    ON Table1.Id = Table3.Id
LEFT JOIN LookUp 
    ON Table1.StatusId = LookUp.Id
    OR (LookUp.Id = 3 AND Table3.Date IS NOT NULL)

结果:

Id  StatusId    Date            Name
1   1           NULL            Test
2   2           NULL            New
3   NULL        NULL            NULL
4   1           NULL            Test
5   2           NULL            New
6   NULL        NULL            NULL
7   1           NULL            Test
8   2           NULL            New
9   NULL        NULL            NULL
10  1           NULL            Test
11  2           NULL            New
12  NULL        27.06.2019      InProgress
13  1           NULL            Test
14  2           NULL            New
15  NULL        NULL            NULL
16  1           NULL            Test
17  2           NULL            New
18  NULL        NULL            NULL
19  1           NULL            Test
20  2           NULL            New
21  NULL        NULL            NULL
22  1           NULL            Test
23  2           NULL            New
24  NULL        27.06.2019      InProgress
25  1           NULL            Test
26  2           NULL            New
27  NULL        NULL            NULL
28  1           NULL            Test
29  2           NULL            New
30  NULL        NULL            NULL

您还可以在rextester.上观看实时演示

答案 1 :(得分:0)

创建一个SQL函数,该函数根据ID返回Name。

Create FUNCTION [dbo].[GetLookUpValue] 
(
@Id int
)
RETURNS varchar(500)
AS BEGIN
    return(Select Name from LOOKUP_table with(nolock) where Id=@Id)
END