从1到多关系表返回最新记录

时间:2017-12-23 01:50:47

标签: sql-server tsql azure-sql-database

我有两个名为Visit和VisitMovement的表,它们是1对多关系,即1个访问可以有许多VisitMovement行。我已经取出了所有细节字段,但这些是表格定义:

CREATE TABLE [dbo].[Visit]
(
    [VisitID] [int] IDENTITY(1,1) NOT NULL
)

CREATE TABLE [dbo].[VisitMovement](
    [VisitMovementID] [int] IDENTITY(1,1) NOT NULL,
    [VisitID] [int] NOT NULL
)

很多时候我需要返回访问以及最新的VisitMovement行中的详细信息。

目前我所做的就是拥有这两个视图,但随着时间的推移它会变慢。

例如,如果我从vwGetVisit中选择*,其中VisitID = 1245,则需要几秒钟才能返回,并且vwLatestVisitMovement对象的成本大部分都在结束。

实现这一目标的更好方法是什么?

CREATE VIEW [dbo].[vwGetVisit] as
        SELECT 
                V.*
                VM.*
            FROM 
                Visit V
            INNER JOIN VisitMovement VM ON
                V.VisitID = VM.VisitID
            INNER JOIN vwLatestVisitMovement LVM on
                VM.VisitMovementID = LVM.VisitMovementID
           ....many other joins including left joins....

CREATE View [dbo].[vwLatestVisitMovement] 
AS
    SELECT
        VisitID,
        max(VisitMovementID) as VisitMovementID
    FROM
        dbo.VisitMovement
    GROUP BY
        VisitID

2 个答案:

答案 0 :(得分:1)

您在VisitMovementID上使用vwLatestVisitMovement加入visitMovement。这对我来说很奇怪... vwLatestVisitMovement .VisitMovementId是使用MAX计算的,并且需要花费大量的时间来加入这个字段。我认为可以更自然地通过VisitID上的访问加入vwLatestVisitMovement,你应该得到相同的结果,但更好的查询计划。

如果您需要来自VisitMOvement的alla数据,您可以使用CROSS APPLY或ROW_NUMBER()OVER。

通常我更喜欢ROW_NUMBER()OVER。

试试这个,看看性能是否更好:

CREATE VIEW [dbo].[vwGetVisit] as
        SELECT 
                V.*
                , LVM.*
            FROM 
                Visit V
            INNER JOIN vwLatestVisitMovement LVM on
                V.VisitID = LVM.VisitID                
           ....many other joins including left joins....

CREATE View [dbo].[vwLatestVisitMovement] 
AS
    WITH LVM AS (
        -- replace * with fields!
        SELECT VM.*
            , ROW_NUMBER() OVER(PARTITION BY VM.VisitID ORDER BY VM.VisitMovementID DESC) AS CheckLastId
        FROM dbo.VisitMovement AS VM
    )
    SELECT
        *
    FROM
        LVM
    WHERE CheckLastId = 1
GO

交叉appply:

CREATE VIEW [dbo].[vwGetVisit] as
        SELECT 
                V.*
                , LVM.*
            FROM 
                Visit V
            CROSS APPLY (SELECT TOP (1) LM.* FROM dbo.VisitMovement AS LM WHERE LM.VisitID = V.VisitID ORDER BY LM.VisitMovementID DESC ) AS LVM
           ....many other joins including left joins....

答案 1 :(得分:0)

three.min.js:326 - Uncaught TypeError: Cannot read property 'x' of undefined上的索引应该有助于解决您的问题:

VisitID

视图效果不佳但是,如果继续遇到性能问题,最好还是根据需要重复查询。