在sql中获取每个数据集表中相关行的最佳方法是什么

时间:2014-08-26 05:31:14

标签: sql sql-server stored-procedures dataset

假设我有2个表

 1. Artical(ID,Description,PubDate)
 2. ArticalMedia(ID,ArticalID,MediaURL)

现在我想在stored procedure中获取2个表。

  1. 表1:前5个最新消息
  2. 表2:表1中选择的所有媒体的前5个新闻
  3. 我知道我们可以使用#Temp表来实现这一点。我这只是&最好的办法?或者我们还有其他方法来实现同样的目标吗?

    简单的2个选择语句可能会导致错误的数据,请参阅以下示例:

    select top 5 * from Artical order by PubDate desc
    

    回归Artical的:5,4,3,2,1

       select * from ArticalMedia where ArticalID in (select top 5 ID from Artical order by PubDate desc)
    

    可以返回6,5,4,3,2的媒体。因为新的Artical可能会被插入数据库,在第一次选择&在第二次选择之前。

3 个答案:

答案 0 :(得分:0)

尝试使用轻量级执行计划的优化查询:

SELECT        A.*,AM.*
FROM            ArticalMedia AS AM INNER JOIN
                         Article AS A ON AM.ArticleID = A.ID
WHERE        (AM.ArticleID IN
                             (SELECT        TOP (5) ID
                               FROM            Article
                               ORDER BY PubDate DESC))
ORDER BY A.PubDate DESC

修改2

在SQL fn_split中创建表值函数:

CREATE FUNCTION [dbo].[fn_Split](@sText varchar(8000), @sDelim varchar(20) = ' ')
RETURNS @retArray TABLE (idx smallint Primary Key, value varchar(8000))
AS
BEGIN
DECLARE @idx smallint,
    @value varchar(8000),
    @bcontinue bit,
    @iStrike smallint,
    @iDelimlength tinyint

IF @sDelim = 'Space'
    BEGIN
    SET @sDelim = ' '
    END

SET @idx = 0
SET @sText = LTrim(RTrim(@sText))
SET @iDelimlength = DATALENGTH(@sDelim)
SET @bcontinue = 1

IF NOT ((@iDelimlength = 0) or (@sDelim = 'Empty'))
    BEGIN
    WHILE @bcontinue = 1
        BEGIN

--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.

        IF CHARINDEX(@sDelim, @sText)>0
            BEGIN
            SET @value = SUBSTRING(@sText,1, CHARINDEX(@sDelim,@sText)-1)
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END

--Trim the element and its delimiter from the front of the string.
            --Increment the index and loop.
SET @iStrike = DATALENGTH(@value) + @iDelimlength
            SET @idx = @idx + 1
            SET @sText = LTrim(Right(@sText,DATALENGTH(@sText) - @iStrike))

            END
        ELSE
            BEGIN
--If you can’t find the delimiter in the text, @sText is the last value in
--@retArray.
 SET @value = @sText
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END
            --Exit the WHILE loop.
SET @bcontinue = 0
            END
        END
    END
ELSE
    BEGIN
    WHILE @bcontinue=1
        BEGIN
        --If the delimiter is an empty string, check for remaining text
        --instead of a delimiter. Insert the first character into the
        --retArray table. Trim the character from the front of the string.
--Increment the index and loop.
        IF DATALENGTH(@sText)>1
            BEGIN
            SET @value = SUBSTRING(@sText,1,1)
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END
            SET @idx = @idx+1
            SET @sText = SUBSTRING(@sText,2,DATALENGTH(@sText)-1)

            END
        ELSE
            BEGIN
            --One character remains.
            --Insert the character, and exit the WHILE loop.
            INSERT @retArray (idx, value)
            VALUES (@idx, @sText)
            SET @bcontinue = 0  
            END
    END

END

RETURN
END

然后查询将是:

DECLARE @tmp nvarchar(max);

select @tmp = stuff((select top 5 ', ', cast(id as nvarchar(max))
FROM Article
ORDER BY PubDate DESC
for xml path ('')
), 1, 2, '');

SELECT        A.*,AM.*
 FROM ArticalMedia AS AM INNER JOIN
      Article AS A ON AM.ArticleID = A.ID
    WHERE        (AM.ArticleID IN (select value from dbo.fn_split(@tmp,',')))
    ORDER BY A.PubDate DESC

答案 1 :(得分:0)

获取TOP 5条记录,然后将它们加入ArticleMedia表格:

SELECT *
FROM 
(
    SELECT TOP 5 ID,Description,PubDate
    FROM Artical
    ORDER BY PubDate DESC
) DS
INNER JOIN ArticleMedia AM
    ON DS.[Id] = AM.[id]

答案 2 :(得分:0)

使用CTE保持简单:

with Top5Artical as (
  select top (5) Artical.ID as ArticleID
  from Artical
  order by Artical.PubDate desc
),
insert into #Table1
select Top5.ArticalID,
  Art.Description,
  Art.PubDate
from Top5Artical as Top5
inner join Artical as Art
  on Top5.ArticalID = Art.ID
order by Top5.PubDate desc;

insert into #Table2
select Top5.ArticalID,
  ArtMedia.ID,
  ArtMedia.URL
from Top5Artical as Top5
inner join ArticalMedia as ArtMedia
  on Top5.ArticalID = ArtMedia.ArticalID
order by Top5.PubDate desc;

select * from #Table1;
select * from #Table2;