views:

608

answers:

4

I have a bidding table, as follows:

SellID INT FOREIGN KEY REFERENCES SellItem(SellID),
CusID INT FOREIGN KEY REFERENCES Customer(CusID),
Amount FLOAT NOT NULL,
BidTime DATETIME DEFAULT getdate()

Now in my website I need to show the user the current bids; only the highest bid but without repeating the same user.

  SELECT CusID, 
         Max(Amount) 
    FROM Bid 
   WHERE SellID = 10 
GROUP BY CusID 
ORDER BY Max(Amount) DESC

This is the best I have achieved so far. This gives the CusID of each user with the maximum bid and it is ordered ascending. But I need to get the BidTime for each result as well. When I try to put the BidTime in to the query:

  SELECT CusID, 
         Max(Amount), 
         BidTime 
    FROM Bid 
   WHERE SellID = 10 
GROUP BY CusID 
ORDER BY Max(Amount) DESC 

I am told that "Column 'Bid.BidTime' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."

Thus I tried:

  SELECT CusID, Max(Amount), BidTime 
    FROM Bid 
   WHERE SellID = 10 
GROUP BY CusID, BidTime 
ORDER BY Max(Amount) DESC

But this returns all the rows. No distinction. Any suggestions on solving this issue?

+1  A: 

One way, assuming another way of thinking about it is to return the LATEST bid by each user:

SELECT b.cusID, b2.LatestBidTime, b.Amount 
FROM Bid b
    JOIN (
        SELECT cusID, MAX(BidTime) AS LatestBidTime
        FROM Bid
        WHERE SellID = 10
        GROUP BY cusID) b2 ON b.cusID = b2.cusID AND b.BidTime = b2.LatestBidTime
WHERE b.SellID = 10
AdaTheDev
The error and such implies that the OP wants the bidtime for the max bid value, but I'm looking for clarification on that.
OMG Ponies
This works :) But i need to brush up my knowledge on joins...As AdaTheDev was the first to answer, i assume it is fair to mark his answer as the accepted. However OMG Ponies gave a wonderful explanation too :)
Ranhiru Cooray
A: 

Presumably the highest bid was made most recently, right? So just put MAX on BidTime too.

SELECT CusID, Max(Amount), MAX(BidTime)
FROM Bid 
WHERE SellID=10 
GROUP BY CusID ORDER BY Max(Amount) DESC 
Gabe
The MAX(bidtime) isn't guaranteed to be associated with the MAX(amount) value.
OMG Ponies
That would be the obvious case, but unfortunately i do not validate whether the bid to be made is higher than the current highest bid.
Ranhiru Cooray
Most bidding systems do not let you submit new bids lower than previous ones, so it's not always an invalid assumption.
Gabe
Yes i completely agree and it is and should definitely be the case.
Ranhiru Cooray
+1  A: 
select b.*
from Bid b
inner join (
    SELECT CusID, Max(Amount) as MaxBid
    FROM Bid 
    WHERE SellID=10 
    GROUP BY CusID 
) bm on b.CusID = bm.CusID and b.Amount = bm.MaxBid
where b.SellID = 10
ORDER BY b.Amount DESC 
RedFilter
+2  A: 

Use:

  SELECT b.cusid,
         b.amount,
         b.bidtime
    FROM BID b
    JOIN (SELECT t.cusid,
                 t.sellid,
                 MAX(t.amount) AS max_amount
            FROM BID t
           WHERE t.sellid = 10
        GROUP BY t.cusid, t.sellid) x ON x.max_amount = b.amount
                                     AND x.cusid = b.cusid
                                     AND x.sellid = b.sellid
ORDER BY b.amount DESC

Using aggregates means you can not get information at that given value in the same query. You have to associate a copy of the table with the aggregated data (joins are the typical choice) to get the related information.

OMG Ponies
This is incorrect and could cause records to be excluded, since it is getting the highest bid for a `cusid` across **all** `sellid`s. If the same `cusid` has bid on more than one `sellid`, and they bid higher on a `sellid <> 10`, the `group by` will return that higher value which will not match anything in `b` due to the restrictive where clause, resulting in that row being filtered out.
RedFilter
@OrbMan: Corrected, thank you.
OMG Ponies