我想从SQL Server进行特殊查询。它来自2个表:
catParentId
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
答案 0 :(得分: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 clause。这个over子句在LS_Mssage表中添加了一个新列,我称之为RN。 RN是一个自动增加索引,每次CatID更改(PARTITION BY)时都会重新启动,并应用于按日期降序排序的结果(ORDER BY [Date] DESC)。这意味着最新的一个将始终具有1的RN。然后,我只在查看RN为1的行时加入此表。
要真正理解这一点,请自行运行此查询:
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CatID ORDER BY [Date] DESC) AS RN
FROM LS_Mssage
查看并了解新表。
这比你的代码快得多,这个表只需要创建一次,但是在循环中,需要为循环的每次迭代完成相同数量的工作。这就是在使用SQL时需要考虑集合(或查询)的原因。