SQL中的函数用于JOIN条件

时间:2017-06-02 11:32:09

标签: sql-server function

这是我的疑问:

SELECT main.SomeValues, mainData.Name
  FROM dbo.MainTable main JOIN 
       dbo.MainDataTable mainData ON 
            (main.dataId = mainData.dataId) AND 
            (mainData.Type = 1 OR mainData.Type = 2 OR mainData.Type = 3)

我在许多视图中使用类似的查询。但最后一个条件始终如一:main.Type = 1 OR main.Type = 2 OR main.Type = 3

我想知道如何将其解压缩到一些SQL函数。我之前从未做过任何功能。

所以它看起来像这样:

SELECT main.SomeValues, mainData.Name
FROM dbo.MainTable main
JOIN dbo.MainDataTable mainData ON main.dataId = mainData.dataId
       AND (GetConditionForType())  -- more or less ;)

2 个答案:

答案 0 :(得分:1)

您可以创建如下视图:

  create view dbo.FilteredMainDataTable
  as
     select ...
     from dbo.MainDataTable 
     where [Type] in (1,2,3);

然后在所有查询中使用此视图而不是dbo.MainDataTable。编译器做什么然后它在每个使用此视图的查询中“打开”视图作为其定义,这就是您想要的。函数不会这样做,它们不被视为“宏替换”

如果你坚持使用功能,你可以创建它,但它不会有你想要的“外观”。它可以是内联表值函数,如下所示:

create function dbo.fn_FilteredMainDataTable(@n1 int, @n2 int, @n3 int)
returns TABLE
    return select Id, ...
    from FilteredMainDataTable
    where type in (@n1, @n2, @n3);  

然后您加入此函数而不是MainDataTable,如下所示:

SELECT main.SomeValues, mainData.Name
FROM dbo.MainTable main
JOIN dbo.fn_FilteredMainDataTable(1,2,3) mainData ON main.dataId = mainData.dataId

^^^^^^^^^^^^^^^^^^^^^^^

以下代码显示了内联表如何在搜索谓词中使用视图推送:

    if object_id('dbo.num') is not null drop table dbo.num;
    go

    select top 1000000
           isnull(row_number() over(order by 1 / 0), 0) as n,
           isnull(row_number() over(order by 1 / 0), 0) as n1
    into dbo.num
    from sys.columns c1 cross join sys.columns c2 cross join sys.columns c3;
    go

    alter table dbo.num add constraint PK_num_n primary key (n);
    go

    create index ix_n1_n on dbo.num (n1, n);
    go

    if object_id('dbo.fn_num_between') is not null drop function dbo.fn_num_between;
    go


    create function dbo.fn_num_between(@n1 int, @n2 int)
    returns table
    as
       return 
       select n, n1
       from dbo.num
       where n between @n1 and @n2;
    go

    select *
    from dbo.fn_num_between(1, 1000)
    where n1 = 5;

seek predicate

答案 1 :(得分:0)

您可以使用内联表值函数执行此操作。 您可以将函数定义为:

create function fnFilteredTypes ()
returns table as return
(
        select 1 as type
        union
        select 2 as type
        union
        select 3 as type

);

然后你可以像这样加入这个函数:

SELECT main.SomeValues, mainData.Name
FROM dbo.MainTable AS main
JOIN dbo.MainDataTable AS mainData
    ON main.dataId = mainData.dataId
JOIN fnFilteredTypes() As typeFilter
    ON(mainData.Type=typeFilter.type)

我不确定这个查询是否真的是你想要的,但基本上你可以理解你可以使用这个函数,就像它是一个参数化视图&直接加入它的字段。只是不要忘记它是一个功能&你用圆括号来称呼它。