我有一个名为books的表(book_name,price)我正在使用SQL SERVER 2008 我需要获得他们有最高价格的前2本书
我用过这个:
Select * From bb n Where (Select Count(book) From bb
Where book <> n.book
And
price > n.price
) >=2 // or 3 it must be flexible
但给了我错误的答案:(。
不允许使用'top'操作或order by OLAP功能 只是简单的查询..
答案 0 :(得分:1)
免责声明:我不鼓励任何人在任何现实生活中遵循本文所述的技巧。我只是因为它的理论挑战而追问这个问题。
我认为这是一个理论/教科书/家庭作业问题,我无法想到不在现实生活中使用order by
的理由,但这里有:
SELECT * FROM bb
WHERE price = (SELECT MAX(price) FROM bb)
OR price = (SELECT MAX(price) FROM bb WHERE price < (SELECT MAX(price) FROM bb))
请注意,如果您的价格列不唯一,则会生成2行以上。你可以解决这个问题但是它有点复杂:D
;WITH ids AS
(
SELECT id FROM bb
WHERE price = (SELECT MAX(price) FROM bb)
OR price = (SELECT MAX(price) FROM bb
WHERE price < (SELECT MAX(price) FROM bb))
)
SELECT * FROM bb
WHERE id = (SELECT MAX(id) FROM ids)
OR id = (SELECT MAX(id) FROM ids WHERE id < (SELECT MAX(id) FROM ids))
但是,如果你真的只想要前两个价格,你可以这样做:
SELECT MAX(price) as price FROM bb
UNION
SELECT MAX(price) FROM bb WHERE price < (SELECT MAX(price) FROM bb)
编辑#62
好吧,我弄清楚了,花了我足够长的时间。你甚至让我在使用递归cte的时候捣乱,直到我意识到它真的很简单,就像为每条记录分配排名并丢弃垃圾一样简单。此查询高度效率低,但它到目前为止满足您的所有要求。另请注意,结果未订购。这正是order by
的用途:D
DECLARE @NumberOfRecords int
SET @NumberOfRecords = 3
;WITH bb_extended AS
(
SELECT
(
SELECT COUNT(*) + 1 FROM bb AS bb2
WHERE bb2.price > bb.price
OR (bb2.price = bb.price AND bb2.id < bb.id)
) AS rank,
*
FROM
bb
)
SELECT * FROM bb_extended
WHERE rank <= @NumberOfRecords
你甚至可以进一步压缩(但你丢失了等级信息):
DECLARE @NumberOfRecords int
SET @NumberOfRecords = 3
SELECT * FROM bb WHERE @NumberOfRecords > (
SELECT COUNT(*) + 1 FROM bb AS bb2
WHERE bb2.price > bb.price
OR (bb2.price = bb.price AND bb2.id < bb.id)
)
<强>严重。不要这样做。
答案 1 :(得分:-1)
您可以使用排名功能代替top
with cte as(
select *,row_number() over(order by price desc) as price from table
)
select * from cte where price<=2