SQL Server-包含TOP 1选择列的视图

时间:2019-07-18 19:22:29

标签: sql-server view

我有一个客户表,然后有一个单独的交易表可以交叉引用客户表。我想用一个特定的列作为合并的SQL视图呈现给使用者。该交易列称为 LastEdited

如果我通过查询FirstName,LastName等列来运行SELECT语句,则视图本身很好。遇到问题的地方是查询 LastEdited 列时。该列使用的是TOP 1选择标准。例如,如果我查询 LastEdited BETWEEN'1/1/2019 00:00:01'和'6/30/2019 23:59:59'。由于存在明显的性能损失,因此结果需要很长时间。

关于如何最好地处理此问题的任何建议?我尝试通过调用标量函数来为此视图创建列,例如:

(选择dbo.fncUser_LastCustomerEditDate(c.CustomerNo))作为LastEdited

此标量函数基本上返回TOP 1记录。我还尝试通过针对外部应用程序引用该列来创建该列,例如:

... 外部应用(从dbo.tbl121_DataLog dl中选择前1个GMTTimestamp,其中dl.PrimaryKey = c.Id和dl.DBActionId在(600001,600002)中按dl.GMTTimeStamp DESC顺序排列)dl

以便我的SELECT列表仅显示:

dl.GMTTimeStamp为LastEdited

这两个选项都不能使我能够通过查询基于此列的结果视图来快速返回结果。

任何帮助或建议将不胜感激!

以下是到目前为止我尝试过的两种视图构造:

CREATE VIEW [dbo].[viwUser_Customers_Custom2]
AS
SELECT     c.Id, c.Type, c.CustomerNo, sit.Code AS PrimarySiteCode, sit.Name AS PrimarySiteName, emp.Code AS PrimarySalespersonCode, 
                      emp.Name AS PrimarySalespersonName, c.Title, c.FirstName, c.MiddleName, c.LastName, c.NickName, c.Greeting, c.PreviousName, 
                      dbo.fncCustContactMethodText(c.PreferredContactMethod) AS PreferredContactMethod, cad.Address1, cad.Address2, cad.Address3, cad.City, cad.State, 
                      cad.PostCode, cad.Country, cpp.CountryPrefix AS PhoneCountryPrefix, cpp.AreaCode AS PhoneAreaCode, cpp.Number AS PhoneNumber, 
                      cpp.Extension AS PhoneExtension, dbo.fncCustFormattedPhoneNo(cpp.CountryPrefix, cpp.AreaCode, cpp.Number, cpp.Extension) 
                      AS PhoneNumberFormatted, cpf.CountryPrefix AS FaxCountryPrefix, cpf.AreaCode AS FaxAreaCode, cpf.Number AS FaxNumber, 
                      cpf.Extension AS FaxExtension, dbo.fncCustFormattedPhoneNo(cpf.CountryPrefix, cpf.AreaCode, cpf.Number, cpf.Extension) AS FaxNumberFormatted, 
                      cpm.CountryPrefix AS MobileCountryPrefix, cpm.AreaCode AS MobileAreaCode, cpm.Number AS MobileNumber, cpm.Extension AS MobileExtension, 
                      dbo.fncCustFormattedPhoneNo(cpm.CountryPrefix, cpm.AreaCode, cpm.Number, cpm.Extension) AS MobileNumberFormatted, cpe.EmailAddress, c.Sex, 
                      c.UDFList1, c.UDFList2, c.UDFList3, c.UDFList4, c.UDFList5, c.UDFList6, c.UDFList7, c.UDFList8, c.UDFList9, c.UDFList10, c.UDFList11, c.UDFList12, 
                      c.FingerSize1 AS LeftLittleFingerSize, c.FingerSize2 AS LeftRingFingerSize, c.FingerSize3 AS LeftMiddleFingerSize, 
                      c.FingerSize4 AS LeftIndexFingerSize, c.FingerSize5 AS LeftThumbSize, c.FingerSize6 AS RightThumbSize, c.FingerSize7 AS RightIndexFingerSize, 
                      c.FingerSize8 AS RightMiddleFingerSize, c.FingerSize9 AS RightRingFingerSize, c.FingerSize10 AS RightLittleFingerSize, c.LeftWristSize, 
                      c.RightWristSize, c.NeckSize, c.SocSecNumber, c.POSComments, c.SecureComments, c.Status, c.Active, c.Day, c.Month, c.Year, dbo.fncGetDOB(c.Day, 
                      c.Month, c.Year) AS BirthDate, dbo.fncGetAge(c.Day, c.Month, c.Year, c.Age, c.AgeReferenceDate, GETDATE()) AS Age, CAST('' AS varchar(1000)) 
                      AS MailingName, CAST('' AS varchar(1000)) AS GreetingName, CAST(0 AS money) AS CustomerSalesTotalForDateRange, CAST(0 AS money) 
                      AS CustomerSalesTotal, CAST('' AS varchar(50)) AS PartnerCustomerNo, CAST('' AS varchar(20)) AS PartnerBirthDate, CAST(0 AS money) 
                      AS PartnerSalesTotalForDateRange, CAST(0 AS money) AS PartnerSalesTotal, dbo.fnc604S_GetAnniversary(c.Id) as Anniversary,
        Coalesce((Select Top 1 cd.DiscountPercent From tbl605_CustDiscount cd Where cd.CustomerId = c.Id),0) as DiscountPercent, 
            dl.GMTTimeStamp as LastEdited
FROM         dbo.tbl600_Customer AS c INNER JOIN
                      dbo.tbl103_Sites AS sit ON c.SiteId = sit.Id LEFT OUTER JOIN
                      dbo.tbl601_CustAddress AS cad ON cad.CustomerId = c.Id AND cad.[Default] = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpp ON cpp.CustomerId = c.Id AND cpp.Device = 1 AND cpp.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpf ON cpf.CustomerId = c.Id AND cpf.Device = 3 AND cpf.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpm ON cpm.CustomerId = c.Id AND cpm.Device = 2 AND cpm.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpe ON cpe.CustomerId = c.Id AND cpe.Device = 4 AND cpe.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl405_Employees AS emp ON dbo.fnc600S_GetPrimarySalespersonId(c.Id) = emp.Id OUTER APPLY
                      (SELECT top 1 GMTTimestamp from dbo.tbl121_DataLog dl where dl.PrimaryKey = c.Id and dl.DBActionId In (600001, 600002) order by dl.GMTTimeStamp DESC) dl



GO





CREATE VIEW [dbo].[viwUser_Customers_Custom]
AS
SELECT     c.Id, c.Type, c.CustomerNo, sit.Code AS PrimarySiteCode, sit.Name AS PrimarySiteName, emp.Code AS PrimarySalespersonCode, 
                      emp.Name AS PrimarySalespersonName, c.Title, c.FirstName, c.MiddleName, c.LastName, c.NickName, c.Greeting, c.PreviousName, 
                      dbo.fncCustContactMethodText(c.PreferredContactMethod) AS PreferredContactMethod, cad.Address1, cad.Address2, cad.Address3, cad.City, cad.State, 
                      cad.PostCode, cad.Country, cpp.CountryPrefix AS PhoneCountryPrefix, cpp.AreaCode AS PhoneAreaCode, cpp.Number AS PhoneNumber, 
                      cpp.Extension AS PhoneExtension, dbo.fncCustFormattedPhoneNo(cpp.CountryPrefix, cpp.AreaCode, cpp.Number, cpp.Extension) 
                      AS PhoneNumberFormatted, cpf.CountryPrefix AS FaxCountryPrefix, cpf.AreaCode AS FaxAreaCode, cpf.Number AS FaxNumber, 
                      cpf.Extension AS FaxExtension, dbo.fncCustFormattedPhoneNo(cpf.CountryPrefix, cpf.AreaCode, cpf.Number, cpf.Extension) AS FaxNumberFormatted, 
                      cpm.CountryPrefix AS MobileCountryPrefix, cpm.AreaCode AS MobileAreaCode, cpm.Number AS MobileNumber, cpm.Extension AS MobileExtension, 
                      dbo.fncCustFormattedPhoneNo(cpm.CountryPrefix, cpm.AreaCode, cpm.Number, cpm.Extension) AS MobileNumberFormatted, cpe.EmailAddress, c.Sex, 
                      c.UDFList1, c.UDFList2, c.UDFList3, c.UDFList4, c.UDFList5, c.UDFList6, c.UDFList7, c.UDFList8, c.UDFList9, c.UDFList10, c.UDFList11, c.UDFList12, 
                      c.FingerSize1 AS LeftLittleFingerSize, c.FingerSize2 AS LeftRingFingerSize, c.FingerSize3 AS LeftMiddleFingerSize, 
                      c.FingerSize4 AS LeftIndexFingerSize, c.FingerSize5 AS LeftThumbSize, c.FingerSize6 AS RightThumbSize, c.FingerSize7 AS RightIndexFingerSize, 
                      c.FingerSize8 AS RightMiddleFingerSize, c.FingerSize9 AS RightRingFingerSize, c.FingerSize10 AS RightLittleFingerSize, c.LeftWristSize, 
                      c.RightWristSize, c.NeckSize, c.SocSecNumber, c.POSComments, c.SecureComments, c.Status, c.Active, c.Day, c.Month, c.Year, dbo.fncGetDOB(c.Day, 
                      c.Month, c.Year) AS BirthDate, dbo.fncGetAge(c.Day, c.Month, c.Year, c.Age, c.AgeReferenceDate, GETDATE()) AS Age, CAST('' AS varchar(1000)) 
                      AS MailingName, CAST('' AS varchar(1000)) AS GreetingName, CAST(0 AS money) AS CustomerSalesTotalForDateRange, CAST(0 AS money) 
                      AS CustomerSalesTotal, CAST('' AS varchar(50)) AS PartnerCustomerNo, CAST('' AS varchar(20)) AS PartnerBirthDate, CAST(0 AS money) 
                      AS PartnerSalesTotalForDateRange, CAST(0 AS money) AS PartnerSalesTotal, dbo.fnc604S_GetAnniversary(c.Id) as Anniversary,
        Coalesce((Select Top 1 cd.DiscountPercent From tbl605_CustDiscount cd Where cd.CustomerId = c.Id),0) as DiscountPercent, (select dbo.fncUser_LastCustomerEditDate(c.CustomerNo)) as LastEdited
FROM         dbo.tbl600_Customer AS c INNER JOIN
                      dbo.tbl103_Sites AS sit ON c.SiteId = sit.Id LEFT OUTER JOIN
                      dbo.tbl601_CustAddress AS cad ON cad.CustomerId = c.Id AND cad.[Default] = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpp ON cpp.CustomerId = c.Id AND cpp.Device = 1 AND cpp.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpf ON cpf.CustomerId = c.Id AND cpf.Device = 3 AND cpf.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpm ON cpm.CustomerId = c.Id AND cpm.Device = 2 AND cpm.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl602_CustPhone AS cpe ON cpe.CustomerId = c.Id AND cpe.Device = 4 AND cpe.DeviceDefault = 1 LEFT OUTER JOIN
                      dbo.tbl405_Employees AS emp ON dbo.fnc600S_GetPrimarySalespersonId(c.Id) = emp.Id

GO

查询SQL视图需要1-2分钟的时间。

1 个答案:

答案 0 :(得分:0)

我找到了一种更简单的方法来完成此任务。只需添加一个SQL触发器即可将带有时间戳的行插入到补充表中。该表将具有适当的构造以使查找更快。