0

我想从 SQL Server 进行特殊查询。它来自2张桌子:

  1. 有列的猫表catParentId
  2. catId列相关的消息表

我想通过 catId 获取与该类别相关的最后一条消息详细信息的猫。换句话说,我想获得父猫下每只猫的最后一条消息。

我创建了表变量并将值插入其中。这是最好的表现方式吗?

SP代码:

USE [Lovely_umbraco_cms]
GO
/****** Object:  StoredProcedure [dbo].[SP_Categories_GetCatsMsgs]    Script Date: 12/30/2012 01:21:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_Categories_GetCatsMsgs]
 @CatId int
AS
set @catId =1;
declare @CatMessages Table(
     RowID       INT    IDENTITY ( 1 , 1 ), 
     CatName Nvarchar(50),
     MessageCount int,
     LastMessageName nvarchar(50),
     OwnerID uniqueidentifier, 
     CreatedDate date,
     Watched int,
     commentCount int
)
--------------- @CatTable --------
declare @RowsCount int;
Set @rowscount =1;

declare @CatTable table(
    id int identity(1,1),
    catId int,
    CatName nvarchar(50),
    CatParentId int
); 
--- Insert into @CatTable
insert into @CatTable(catId,catName,CatParentId )
select catId, CatName ,CatParentId from LS_Categories WHERE(CatParentId = @CatId);
-----------------------------------

declare @CatTableID int;

declare @CatName nvarchar(50);

-------Temp Message Table --------
declare @Temp_MessagesTable table(
    [Subject] nvarchar(255),
    [Date] [nvarchar](15) NULL,
    [OwnerId] [uniqueidentifier] NULL,
    [WatchCount] [bigint] NULL
);
--------------- @CatMessages Varibles-----

     declare @MessageCount int;
     declare @LastMessageName nvarchar(50);
     declare @OwnerID uniqueidentifier; 
     declare @CreatedDate date;
     declare @Watched int;
     declare @commentCount int;
-------
while @rowsCount <=(SELECT count(Catid) FROM  @CatTable)
begin
    select @CatTableID = CatId, @CatName = CatName from @CatTable where id= @rowsCount;

    delete from @Temp_MessagesTable;

    insert into @Temp_MessagesTable ([Subject],[Date],[OwnerId],[WatchCount])(
    SELECT      Subject, Date, OwnerId, WatchCount
    FROM         (SELECT     TOP (1) Subject, Date, OwnerId, WatchCount
    FROM         LS_Mssages 
    WHERE     (CatId = @CatTableID) ORDER BY MsgId DESC
    ) as s 
    );
    select @LastMessageName=[Subject],@CreatedDate=[Date],
            @OwnerID=[OwnerId],@Watched= [WatchCount] from @Temp_MessagesTable

    -- insert into CatMessages Table
    insert into @CatMessages(CatName,MessageCount,LastMessageName,OwnerID,CreatedDate,Watched,commentCount)
                             (select @CatName,@MessageCount,@LastMessageName,@OwnerID,@CreatedDate,@Watched,@commentCount);
    set @rowsCount = @rowsCount+1
End

select * from @CatMessages;

我的表:http ://ss-projects.com/t1.jpg

数据样本:http ://ss-projects.com/data.jpg

结果:http ://ss-projects.com/result.jpg

4

1 回答 1

4

这不是在 SQL 中执行此操作的最佳方法。

SQL 不是为循环而设计的,相反,您希望编写同时处理所有元素的查询,而不是一次处理一个。

以下与您的代码代码相同,并且还突出显示了错误(选择列表中的 NULLS)。

INSERT INTO CatMessages
  SELECT C.CatName, M.Subject, NULL as LastMessageName, M.OwnerID, M.Date, M.WatchCount, NULL as CommentCount
  FROM CatTable C
  JOIN LS_Mssage M ON C.CatID = M.CatID

限制 LS_Mssage 表的最简单方法:

INSERT INTO CatMessages
  SELECT C.CatName, M.Subject, NULL as LastMessageName, M.OwnerID, M.Date, M.WatchCount, NULL as CommentCount
  FROM CatTable C
  JOIN (SELECT *, ROW_NUMBER() OVER (PARTITION BY CatID ORDER BY [Date] DESC) AS RN
        FROM LS_Mssage) M ON C.CatID = M.CatID AND M.RN = 1

这是如何工作的:

首先请阅读 JOINS 在 SQL 中的工作原理。这是一个很深的话题,在网络上的任何搜索都会给你带来比我在这短短的篇幅中写的更好的解释。

我使用的高级技术是OVER 子句。这个 over 子句向我称之为 RN 的 LS_Mssage 表添加了一个新列。RN 是一个自动递增索引,每次 CatID 更改时都会重新启动 (PARTITION BY),并应用于按日期降序排序的结果 (ORDER BY [Date] DESC)。这意味着最新的 RN 总是为 1。然后我加入这个表,只查看 RN 为 1 的行。

要真正理解这一点,请自行运行此查询:

SELECT *, 
       ROW_NUMBER() OVER (PARTITION BY CatID ORDER BY [Date] DESC) AS RN
FROM LS_Mssage

查看并了解新表。

这比您的代码快得多,该表只需创建一次,但是在循环中,每次循环迭代都需要完成相同数量的工作。这就是为什么在使用 SQL 时需要在集合(或查询)中思考。

于 2012-12-29T23:49:47.047 回答