2012-03-01 52 views
1

我已经为数据库中的一项操作编写了此存储过程,但它提示出现两个错误。我相当新,最重要的是,如果有人能纠正这个错误,那将会很棒。尝试执行时存储过程中的语法错误

CREATE PROCEDURE findVersions 
    @seg nvarchar(255), 
    @str nvarchar(255) 
AS 

    DECLARE @UnsegQuery AS nvarchar(255) 

    SET @UnsegQuery = SELECT DISTINCT UnsegmQuery 
         FROM tbData 
        WHERE SegQuery = @seg 

    SELECT TOP 1 Strategy, Versions, CGNum 
    FROM tbData 
    WHERE Strategy = @str 
    AND SegQuery = @seg 
ORDER BY CGnum DESC 
    UNION 
    SELECT TOP 1 Strategy, Versions 
    FROM tbData 
    WHERE Strategy = 'BF' 
    AND UnsegmQuery = @UnsegQuery 
    UNION 
    SELECT Strategy, Versions 
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY nDCG DESC) AS rownumber 
      FROM tbData) AS foo 
    WHERE rownumber > 1 

错误:

消息156,级别15,状态1,过程findVersions,行中的关键字10
附近有语法错误 'SELECT'。
消息156,级别15,状态1,过程findVersions,行中的关键字 '联盟'

任何建议近13
语法不正确?

更新 例如:我与查询有什么关系。我必须显示第一个查询的第一个结果,第二个查询的第一个结果以及第一个查询结果的剩余三个结果。

1st class: (has 4 student) 

Tom (Has highest score) 
Rex (Hss second highest score) 
Rambo (HAs 3rd highest score) 
Betty (Has least score) 

2nd class: (has 1 student) 

Spooky (Has the highest score) 

Required result order in DataControl: 

Tom 
Spooky 
Rex 
Rambo 
Betty 
+0

这看起来并不完整 - “@ UnsegQuery”已声明并设置,但从未使用过。 UNION中的第三个查询不正确,因为它是独立的。打破'联盟',并逐渐增加以确定你的问题是什么。 – 2012-03-01 05:08:17

+0

尝试在子查询周围放置括号('SET @UnsegQuery ='后面)。 – 2012-03-01 05:09:18

+0

@JohnPick:请参阅[TSQL:SET vs SELECT](http://stackoverflow.com/questions/3945361/t-sql-set-verus-select-when-assigning-variables) – 2012-03-01 05:09:46

回答

2

为了解决错误“关键字‘SELECT’附近有语法错误”,这句话需要使用SELECT周围括号写:如果你使用SET设置的值

SET @UnsegQuery = (SELECT DISTINCT UnsegmQuery FROM tbData WHERE SegQuery = @seg) 

@UnsegQuery,您还需要确定SELECT只会返回一个值。或者,您可以使用:

SELECT DISTINCT @UnsegQuery = UnsegmQuery FROM tbData WHERE SegQuery = @seg 

设置值为@UnsegQuery。在这种情况下,如果返回多条记录,则@UnsegQuery将设置为最后一条记录的值。

由于在UNION之前不能使用ORDER BY,所以发生“关键字'UNION'附近的语法错误”错误。在最后的UNION声明之后,您只能使用ORDER BY(有关更多信息,请参阅MSDN documentation)。

UPDATE
要从最后的评论回答你的问题,对于查询的最后一部分的正确语法应该是这个样子:

SELECT foo.Strategy, foo.Versions 
FROM (
    SELECT Strategy, Versions, ROW_NUMBER() OVER (ORDER BY nDCG DESC) AS [rownumber] 
    FROM tbData) foo 
WHERE foo.rownumber > 1 

该声明将选择从tbData下令所有记录通过nDCG降序除第一条记录。我不确定这有助于你解决问题,但语法是正确的。

更新2

OK,我想我明白这个问题。你想从表格中选择所有的行,但你希望一个特定的记录是第一个,一个不同的特定记录是第二个,然后是其余的。一种做法是使用CASE WHEN语句将值分配给所需的第一行,所需的第二行,然后按该值进行排序。例如:

DECLARE @myTable TABLE([ID] INT, [Student] VARCHAR(10)) 
INSERT INTO @myTable VALUES(1, 'Tom') 
INSERT INTO @myTable VALUES(2, 'Spooky') 
INSERT INTO @myTable VALUES(3, 'Rex') 
INSERT INTO @myTable VALUES(4, 'Rambo') 
INSERT INTO @myTable VALUES(5, 'Betty') 
DECLARE @firstID INT, @secondID INT 
SET @firstID = 2 
SET @secondID = 4 

SELECT * 
FROM @myTable 
ORDER BY 
    CASE 
     WHEN [ID] = @firstID THEN 1 
     WHEN [ID] = @secondID THEN 2 
     ELSE 3 
    END, 
    [ID] 
+0

SET'现在可以工作,但是你能否推荐一种解决第二个错误的方法?我应该怎么做才能在第一个查询中检索最上面的结果呢? – user1240679 2012-03-01 05:16:04

+0

如果我从第一个查询中删除ORDER BY,奇怪的是它开始显示:最后一个查询的错误:'无效的列名'Strategy'。 列名'QuotedVersions'。' – user1240679 2012-03-01 05:19:48

+0

更新了问题,并为我正在尝试做的事添加了一个示例 – user1240679 2012-03-01 05:22:17