因此,在下面的查询中,我收到以下错误:关键字TOP和ORDER BY旁边的语法不正确。我都没有看到语法问题。经过进一步测试后,看来我的数据库平台不允许在派生表中使用TOP和ORDER BY。有人看到该查询的解决方法吗?我似乎找不到在TOP之后具有整数变量的另一种方法。我正在使用的不幸平台是SqlDbx。
DECLARE @SQL VARCHAR(16384)
DECLARE @CC_N INT
SELECT
@CC_N = B.PP - A.CC_PP
FROM
(
SELECT
Carline,
SUM(PP_Floor) AS CC_PP
FROM PP_Balancing
WHERE Carline = '01'
GROUP BY Carline
) AS A
JOIN PP_National AS B ON A.Carline = B.Carline
SET @SQL =
'
UPDATE PP_Balancing
SET PP_Floor = PP_Floor + 1
WHERE
Sales_Locality IN
(
SELECT TOP '+CAST(@CC_N AS VARCHAR(255))+'
Sales_Locality
FROM PP_Balancing
WHERE Carline = ''01''
ORDER BY PP_Decimal DESC
)
AND Carline = ''01''
'
EXEC (@SQL)
答案 0 :(得分:1)
OP在注释中提到这是一个Sybase ASE 12.5.4实例,因此我们将介绍一些ASE特定的详细信息...
OP尚未提供实际的错误消息,但我猜测它看起来像:
select * from
(select top 4 id
from sysobjects
order by name
) dt
go
Msg 154, Level 15, State 53:
Server 'ASE200', Line 2:
An ORDER BY clause is not allowed in a derived table.
select * from
(select id
from sysobjects
order by name
) dt
go
Msg 154, Level 15, State 53:
Server 'ASE200', Line 3:
An ORDER BY clause is not allowed in a derived table.
这是预期的行为(根据Sybase ASE manuals),即,子查询或派生表中不允许order by
。
虽然子查询(或派生表)中允许top
子句 ,但结果可能不会如预期的那样出来(也不能保证产生相同的结果)重复运行)而没有order by
子句。
因此,剩下的主要问题是如何update
仅行前“ X”行。
现在,Sybase ASE确实允许top
语句中的update
子句,但是由于缺乏对order by
子句(在update
语句中)的支持,{ {1}}在这种情况下(如果必须应用所需的排序)几乎没有用。
由于OP使用变量(@CC_N)确定要更新的行数,因此我假设我们可以使用另一个变量来确定要更新的top
值的范围。
在进入实际的PP_Decimal
语句之前,我们需要看几个中间步骤...
update
在此示例中,我插入了静态-- use variable (@name) to capture the Nth name from sysobjects (order by name)
select top 5 name from sysobjects order by name
go
name
------------------------------
sysalternates
sysattributes
syscolumns
syscomments
sysconstraints <<<=== we want to capture this value in @name
(5 rows affected)
declare @name varchar(255)
-- @name will be assigned each value as it's returned by the query, with
-- the last value (sysconstraints) being the last value assigned to @name
select top 5 @name = name from sysobjects order by name
print @name
go
(5 rows affected)
sysconstraints <<<=== the contents of @name
,但在OPs查询中,我们需要插入变量(5
),这将要求我们动态地构建并执行查询。但是在我们的例子中,它变得更加有趣,因为对于动态查询,我们还需要将查询结果捕获到@CC_N
中,以便以后使用。对我们来说幸运的是,ASE通过在动态创建的查询中加入@name
来做到这一点,例如:
@name
这时,我们应该拥有实现所需的declare @name varchar(30),
@SQL varchar(100),
@CC_N int
select @CC_N = 5
select @SQL = 'select top ' + convert(varchar(30),@CC_N) + ' @name = name from sysobjects order by name'
select @SQL as 'my query'
exec(@SQL)
select @name as '@name'
go
@SQL
-------------------------------------------------------
select top 5 @name = name from sysobjects order by name
@name
------------------------------
sysconstraints <<<=== the contents of @name
所需的一切。
注意:为了得到这个答案,我将假设update
列为整数。
PP_Decimal
注意:此解决方案假定DECLARE @SQL varchar(1000),
@CC_N int,
@PP_Decimal int
-- OPs original code to find the Nth value;
-- removed the superfluous 'group by' from the derived table
SELECT @CC_N = B.PP - A.CC_PP
FROM
(SELECT SUM(PP_Floor) AS CC_PP
FROM PP_Balancing
WHERE Carline = '01'
) AS A
JOIN PP_National AS B ON A.Carline = B.Carline
-- ??? should OP check for @CC_N >= 1 ???
-- find the Nth PP_Decimal value where 'N' == @CC_N
select @SQL =
"select top " + convert(varchar(30), @CC_N) + " @PP_Decimal = PP_Decimal
from PP_Balancing
where Carline = '01'
order by PP_Decimal desc"
-- comment-out/remove the following 'select';
-- only placed here for debugging purposes
select @SQL as '@SQL'
exec(@SQL)
-- at this point @PP_Decimal should contain the last/Nth PP_Decimal value when ordered by PP_Decimal desc;
-- again, following 'select' is for debugging purposes
select @PP_Decimal as '@PP_Decimal'
-- now update our table where PP_Decimal >= @PP_Decimal
update PP_Balancing
set PP_Floor = PP_Floor + 1
where PP_Decimal >= @PP_Decimal
and Carline = '01'
go
@SQL
---------------------------------------
select top 5 @PP_Decimal = PP_Decimal <<<=== for sake of example I plugged in @CC_N=5
from PP_Balancing
where Carline = '01'
order by PP_Decimal desc
@PP_Decimal
-----------
538 <<<=== made up number for the sake of this example (since I don't have any actual data)
(N rows affected) <<<=== assuming update statement finds @CC_N rows to update
的值是唯一的,否则最终的PP_Decimal
可能会更新多个update
的值,例如
@CC_N
max(PP_Decimal) = 47
中有100行PP_Decimal = 47
@CC_N = 5
将设置为@PP_Decimal
和47
不仅会影响@ CC_N = 5行,还会更新所有100行,其中update
用户可能尝试的一些变化是限制要更新的行数,例如:
PP_Decimal >= 47
或
update top 5 ...
但是这些不能保证相同的行会在重复运行时得到更新。
另一种(显而易见的)解决方案是将set rowcount 5
update ...
set rowcount 0
主键(PK)列值拉入#temp表,然后使top @CC_N
与该#temp表联接以执行所需的操作update
个更新。我将等待看#temp表解决方案是否可以被OP接受,和/或让其他人发布带有#temp表解决方案详细信息的答案。