如何修复此SQL查询返回不正确的值?

时间:2011-06-08 11:02:19

标签: sql

我正在编写一个SQL查询,它会返回某个用户丢失的竞价列表,就像在eBay上一样。

这是我的表:

bid_id  bid_belongs_to_auction  bid_from_user   bid_price
6       7                       1               15.00
8       7                       2               19.00
13      7                       1               25.00

有问题的区域是这个(取自我的完整查询,放在问题的最后):

      AND EXISTS (
              SELECT 1 
                FROM bids x 
               WHERE x.bid_belongs_to_auction = bids.bid_belongs_to_auction
                 AND x.bid_price > bids.bid_price
                 AND x.bid_from_user <> bids.bid_from_user
                 )

问题是查询会返回所有出价较高的拍卖,但会忽略用户的更高出价。

因此,上述查询有效的示例:

bid_id  bid_belongs_to_auction  bid_from_user   bid_price
6       7                       1               15.00
7       7                       2               18.00

在这种情况下,用户1因丢失竞价而退回,因为还有另一个出价高于用户出价。

但是,这是查询不起作用的时间

bid_id  bid_belongs_to_auction  bid_from_user   bid_price
6       7                       1               15.00
8       7                       2               19.00
13      7                       1               25.00

在这种情况下,用户1因丢失竞价而被错误地返回,因为还有另一个出价高于之前的某个出价,但是用户已经对此进行了更高的出价。< / p>

如果这很重要,这是我的完整查询,但我认为没有必要解决上述问题,但无论如何我都在这里张贴:

$query = "
   SELECT
      `bid_belongs_to_auction`,
      `auction_unixtime_expiration`,
      `auction_belongs_to_hotel`,
      `auction_seo_title`,
      `auction_title`,
      `auction_description_1`
   FROM (
      SELECT
         `bid_belongs_to_auction`,
         `bid_from_user`,
         MAX(`bid_price`) AS `bid_price`,
         `auctions`.`auction_enabled`,
         `auctions`.`auction_unixtime_expiration`,
         `auctions`.`auction_belongs_to_hotel`,
         `auctions`.`auction_seo_title`,
         `auctions`.`auction_title`,
         `auctions`.`auction_description_1`
      FROM `bids`
      LEFT JOIN `auctions` ON `auctions`.`auction_id`=`bids`.`bid_belongs_to_auction`
      WHERE `auction_enabled`='1' AND `auction_unixtime_expiration` > '$time' AND `bid_from_user`='$userId'
      AND EXISTS (
              SELECT 1 
                FROM bids x 
               WHERE x.bid_belongs_to_auction = bids.bid_belongs_to_auction
                 AND x.bid_price > bids.bid_price
                 AND x.bid_from_user <> bids.bid_from_user
                 )
      GROUP BY `bid_belongs_to_auction`
   ) AS X
   WHERE `bid_from_user`='$userId'
";

3 个答案:

答案 0 :(得分:2)

这是一种不同的方法:

$query = "
   SELECT
      `max_bids`.`bid_belongs_to_auction`,
      `auctions`.`auction_unixtime_expiration`,
      `auctions`.`auction_belongs_to_hotel`,
      `auctions`.`auction_seo_title`,
      `auctions`.`auction_title`,
      `auctions`.`auction_description_1`
   FROM `auctions`
     INNER JOIN (
        SELECT
           `bid_belongs_to_auction`,
           MAX(`bid_price`) AS `auction_max_bid`,
           MAX(CASE `bid_from_user` WHEN '$userId' THEN `bid_price` END) AS `user_max_bid`
        FROM `bids`
        GROUP BY `bid_belongs_to_auction`
     ) AS `max_bids` ON `auctions`.`auction_id` = `max_bids`.`bid_belongs_to_auction`
   WHERE `auctions`.`auction_enabled`='1'
     AND `auctions`.`auction_unixtime_expiration` > '$time'
     AND `max_bids`.`user_max_bid` IS NOT NULL
     AND `max_bids`.`user_max_bid` <> `max_bids`.`auction_max_bid`
";

基本上,当您检索所有拍卖的最高出价时,您还会检索特定用户的最高出价。下一步是将获得的列表加入auctions表,并对用户的最高出价不等于拍卖的最高出价应用额外的过滤器。

注意:`max_bids`.`user_max_bid` IS NOT NULL条件可能是不必要的。在SQL Server中肯定会如此,因为`max_bids`.`user_max_bid` <> `max_bids`.`auction_max_bid`条件会隐含非归零性。我不确定它在MySQL中是否相同。

答案 1 :(得分:1)

未经测试,但这是我接近它的方式。如果有关于userid的索引以及关于auctionid的索引,那么应该执行OK。

           select OurUserInfo.auctionid, OurUserInfo.userid, 
           OurUserInfo.ourusersmaxbid, Winningbids.TopPrice
           from

           (

           select A.auctionid, A.userid, max(A.price) as OurUsersMaxBid
           from auctions A where userid = ?
           group by A.auctionid, A.userid

           ) as OurUserInfo


           inner join


           (                      
          -- get the current winning bids for all auctions in which our user is bidding
           select RelevantAuctions.auctionid, max(auctions.price) as TopPrice
            from auctions inner join            
           (
           select distinct auctionid from auctions where userid = ?  -- get our user's auctions
           ) as RelevantAuctions
           on auctions.auctionid = RelevantAuctions.auctionid
           group by RelevantAuctions.auctionid


            ) as WinninBids


            on OurUserInfo.auctionid = winningbids.auctionid

            where WinninBids.TopPrice > OurUserInfo.ourusersmaxbid

答案 2 :(得分:0)

而不是

SELECT 1
  FROM bids x
 WHERE     x.bid_belongs_to_auction = bids.bid_belongs_to_auction
       AND x.bid_price > bids.bid_price
       AND x.bid_from_user <> bids.bid_from_user

试试这个:

SELECT 1
  FROM (SELECT BID_ID,
               BID_BELONGS_TO_AUCTION,
               BID_FROM_USER,
               BID_PRICE
          FROM (SELECT BID_ID,
                       BID_BELONGS_TO_AUCTION,
                       BID_FROM_USER,
                       BID_PRICE,
                       RANK ()
                       OVER (
                          PARTITION BY BID_BELONGS_TO_AUCTION, BID_FROM_USER
                          ORDER BY BID_PRICE DESC)
                          MY_RANK
                  FROM BIDS)
         WHERE MY_RANK = 1) x
 WHERE     x.bid_belongs_to_auction = bids.bid_belongs_to_auction
       AND x.bid_price > bids.bid_price
       AND x.bid_from_user <> bids.bid_from_user;