如何在查询中使用表类型

时间:2014-07-30 13:11:28

标签: tsql sql-server-2008-r2

我在News表中有9000行,并使用此代码从中选择20:

Select *
From (
      Select *, ROW_NUMBER() OVER (ORDER BY DateSend DESC) AS Num
      From News
      Where SubjectID in(Select MenuSubject.SubjectID
                         From MenuSubject inner join Menu on MenuSubject.MenuID = Menu.MenuID)
) as myTable
where myTable.Num BETWEEN 100 and 120

但是时间是28秒花在阅读上!另外,我使用out连接表测试此查询,并在1秒后得到结果。

所以,我希望使用Table类型来选择连接表并在查询中使用它。我使用以下代码创建了新的Table类型:

DECLARE @MyTable2 IntListTable
Insert Into @MyTable2
Select MenuSubject.SubjectID
From MenuSubject inner join Menu on MenuSubject.MenuID = Menu.MenuID
Select *
From (
      Select *, ROW_NUMBER() OVER (ORDER BY DateSend DESC) AS Num
      From News
      Where SubjectID in @MyTable2
) as myTable
where myTable.Num BETWEEN 100 and 120

但在

中获取错误
  

@ MyTable2中的SubjectID

错误:

'@ MyTable2'附近的语法不正确。


编辑:

我用以下代码测试我的代码:

Select myTable.Title

或使用此代码代替连接表:

Where SubjectID in(13,14,20,21,25,24,26,24,28,29,30,54,55,60,47,98,99,65,14,20,33,666,987,254)

在1秒内得到结果。

但在查询中使用此代码:

Select myTable.MoreText

时间是28秒花在阅读!为什么!?

3 个答案:

答案 0 :(得分:0)

试试这个,

Select x.Num
From (

      Select *, ROW_NUMBER() OVER (ORDER BY DateSend DESC) AS Num
      From News
      Where SubjectID in(Select MenuSubject.SubjectID
                         From MenuSubject inner join Menu on MenuSubject.MenuID = Menu.MenuID)
)  x
where x.Num <21

答案 1 :(得分:0)

WITH myTempTable as (Select MenuSubject.SubjectID
                         From MenuSubject inner join Menu on MenuSubject.MenuID = Menu.MenuID)
Select *
From (
      Select *, ROW_NUMBER() OVER (ORDER BY DateSend DESC) AS Num
      From News
      Where SubjectID in (SELECT SubjectID FROM myTempTable)
) as myTable
where myTable.Num BETWEEN 100 and 120

您可以尝试以上查询。

答案 2 :(得分:0)

此查询中绝对不需要用户定义的表类型。它增加了工作但没有实际的好处。

问题很可能是您正在使用IN列表,因为这些列表会为每个值转换为OR条件。但是也不需要IN列表。

这个查询实际上可以通过根据INNER JOIN重新思考来简化,这应该更好,因为它将允许查询优化器完成它的工作。

SELECT *
FROM (
      SELECT nw.*, ROW_NUMBER() OVER (ORDER BY DateSend DESC) AS [Num]
      FROM News nw
      INNER JOIN (
          MenuSubject
          INNER JOIN Menu
                  ON MenuSubject.MenuID = Menu.MenuID
      ) ON MenuSubject.SubjectID = nw.SubjectID
) AS myTable
WHERE myTable.Num BETWEEN 100 AND 120;

可以进行最后一次简化,虽然我怀疑这里需要它,因为9000行几乎没有数据,首先是将结果转储到本地临时表,然后在INNER JOIN中使用它:

CREATE TABLE #Subjects
(
  SubjectID INT NOT NULL -- PRIMARY KEY -- test with and without PK to see if it helps
);

INSERT INTO #Subjects (SubjectID)
  SELECT MenuSubject.SubjectID
  FROM   MenuSubject
  INNER JOIN Menu
          ON Menu.MenuID = MenuSubject.MenuID;

SELECT *
FROM (
      SELECT nw.*, ROW_NUMBER() OVER (ORDER BY DateSend DESC) AS [Num]
      FROM News nw
      INNER JOIN #Subjects sub
              ON sub.SubjectID = nw.SubjectID
) AS myTable
WHERE myTable.Num BETWEEN 100 AND 120;