SQL CTE 与视图

Posted

技术标签:

【中文标题】SQL CTE 与视图【英文标题】:SQL CTE vs View 【发布时间】:2021-01-17 14:22:47 【问题描述】:

我有一个包含 65,000,000 行的事务表。

它分为大约几百个公司,每个公司又分为几百或几千个独立用户。

例子:

CREATE TABLE [dbo].[TestTransaction]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [CompanyId] [int] NULL,
    [UserId] [int] NULL,
    [LogDateTime] [datetime] NULL,
    [Key1] [nvarchar](20) NULL,
) ON [PRIMARY]
GO

对于特定公司,我需要在用户的最小值LogDateTime 和用户的最大值LogDateTime 处获取所有用户和键值。

我想这样做:

;with cteGetMin as
(
    select 
        CompanyId
        , UserId
        , LogDateTime
        , Key1
        , Row_Number() over (partition by UserId order by LogDateTime) as rowNumMin
    from [dbo].[TestTransaction]
    where CompanyId = @companyId
)
,cteGetMax as
(
    select 
        CompanyId
        , UserId
        , LogDateTime
        , Key1
        , Row_Number() over (partition by UserId order by LogDateTime desc) as rowNumMax
    from [dbo].[TestTransaction]
    where CompanyId = @companyId
)
select 
    ma.CompanyId
    ,ma.UserId
    ,ma.Key1 as MaxKey
    ,ma.LogDateTime as MaxLogDateTime
    ,mi.Key1 as MinKey
    ,mi.LogDateTime as MinLogDateTime
from cteGetMax ma
join cteGetMin mi
    on mi.CompanyId = ma.CompanyId
    and mi.userId = ma.userId
    and mi.rowNumMin = 1
    and ma.rowNumMax = 1

我可以将每个 CTE 分解为一个单独的视图(或索引视图?),但这些视图将在 65,000,000 行的整个表上运行。

我的第一个想法是在每个 CTE 中添加 WHERE 子句会限制子结果,从而提高性能。

有什么想法吗?我应该保留 CTE,还是使用单独的视图?

编辑:我试图说明的一点是,在子查询或 CTE 中使用限制性 WHERE 子句是否更有效,或者拥有对整个 65,000,000 行进行操作的视图是否更有效?

【问题讨论】:

您使用的是哪个 dbms? 使用:SQL 2019 【参考方案1】:

您实际上并不需要两个子查询和一个联接。相反,您可以使用row_number() 以两种方式枚举行,然后过滤一次,然后进行条件聚合:

select CompanyId, UserId,
    max(case when rowNumMax = 1 then Key1 end) as MaxKey,
    max(LogDateTime)                           as MaxLogDateTime,
    min(case when rowNumMin = 1 then Key1 end) as MinKey,
    min(LogDateTime)                           as MinLogDateTime
from (
    select t.*, 
        row_number() over (partition by UserId order by LogDateTime) as rowNumMin,
        row_number() over (partition by UserId order by LogDateTime desc) as rowNumMax
    from [dbo].[TestTransaction] t
    where CompanyId = @companyId
) t
where 1 in (rowNumMin, rowNumMax)
group by CompanyId, UserId

【讨论】:

以上是关于SQL CTE 与视图的主要内容,如果未能解决你的问题,请参考以下文章

CTE 中的 SQL Server 视图导致性能不佳

从任何 SQL 查询/视图/CTE 返回前 1

sql 视图,临时表,CTE,派生表

sql server中的cte

sql 表表达式 - 视图,临时表,表变量,派生表,表值函数,公用表表达式(CTE)

Sql Server 公用表达式(CTE)