使用MySql选择行的子集:有条件地限制所选条目的数量

时间:2013-06-28 17:14:48

标签: mysql sql

这是我之前查询的后续问题。我希望在这种情况下发布一个新问题:Selecting a subset of rows from a PHP table

我有一个看起来像这样的sql表(例如):

id seller price amount
1  tom    350   500
2  tom    350   750
3  tom    350   750
4  tom    370   850
5  jerry  500   1000

我想为每个卖家选择一行:特别是,对于每个卖家,我想要最便宜的价格行,以及该价格的最大金额。在上面的例子中,我想要第2行和第5行(或者3和5,我不关心我得到的2和3中的哪一个,只要我只得到其中一个)。

我正在使用它:

dbquery("SELECT a.* FROM $marketdb a
        INNER JOIN
        (
            SELECT  seller, MAX(amount) amount
            FROM    $marketdb
            WHERE   price=$minprice
            GROUP   BY seller
        ) b ON a.seller = b.seller AND
                a.amount = b.amount;");

但这给了我2,3行和5行,而我只想要第2行和第3行。

我也有一种唠叨的怀疑,即这可能并不总是返回最低价格行。到目前为止,我的测试已被混淆了这样一个事实,即我获得的行数超过给定卖家的相同金额。

如果有人能指出我的错误,我会非常感激。

谢谢!

编辑:道歉,我没有问我的意思。我想从全球最低价格返回行,每个卖家最多1个,而不是每个卖家的最低价格。这只是上面的第2行或第3行。遗憾!

5 个答案:

答案 0 :(得分:2)

只需尝试在卖家处添加另一个组,因为您想要卖家的单行

到最终查询,如

SELECT a.* FROM $marketdb a
INNER JOIN
(
    SELECT  seller, MAX(amount) amount
    FROM    $marketdb
    WHERE   price=$minprice
    GROUP   BY seller
) 
b ON a.seller = b.seller AND
a.amount = b.amount group by a.seller;

答案 1 :(得分:1)

测试 SQL小提琴

http://sqlfiddle.com/#!2/7de03/2/0

CREATE TABLE `sellers` (
  `id` INT UNSIGNED  NOT NULL AUTO_INCREMENT,
  `seller` VARCHAR(16) NOT NULL,
  `price` FLOAT NOT NULL,
  `amount` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`)
);
INSERT INTO `sellers` VALUES (1, 'tom', 350, 500);
INSERT INTO `sellers` VALUES (2, 'tom', 350, 750);
INSERT INTO `sellers` VALUES (3, 'tom', 350, 750);
INSERT INTO `sellers` VALUES (4, 'tom', 350, 850);
INSERT INTO `sellers` VALUES (5, 'jerry', 500, 600);
INSERT INTO `sellers` VALUES (6, 'jerry', 500, 1000);
INSERT INTO `sellers` VALUES (7, 'jerry', 500, 800);

SELECT * FROM
(SELECT DISTINCT * FROM sellers ORDER BY price ASC, amount DESC) t0
GROUP BY seller;

有点......工作:)

答案 2 :(得分:1)

在这个答案的最后有一个丑陋的黑客,但如果你不关心返回哪一行,那么我想它可以节省一些打字。虽然,如果你真的不关心返回哪一行,那往往会指向你的架构设计中一个更基本的缺陷!

 SELECT x.* 
   FROM market x 
   JOIN 
      ( SELECT seller,MIN(price) min_price FROM market GROUP BY seller) y 
     ON y.seller = x.seller 
    AND y.min_price = x.price
   JOIN 
      ( SELECT seller,price,MAX(amount) max_amount FROM market GROUP BY seller,price) z
     ON z.seller = y.seller 
    AND y.min_price = z.price
    AND z.max_amount = x.amount
  GROUP
     BY seller;   

另一种方法,我不喜欢,但在这里受到其他人的欢迎,就像这样......

SELECT x.*         
  FROM 
     ( SELECT * 
         FROM market
        ORDER
           BY seller
            , price
            , amount DESC
            , id
     ) x
 GROUP
    BY seller;

答案 3 :(得分:0)

您可能需要GROUP BY加入之外的卖家列。此外,您的WHERE子句看起来就像价格是设定数字而不是<=

答案 4 :(得分:0)

查询:

<强> SQLFIDDLEExample

SELECT s.* 
FROM sellers s 
WHERE s.id = (SELECT s2.id
              FROM sellers s2
              WHERE s2.seller = s.seller
              ORDER BY s2.price ASC, s2.amount DESC
              LIMIT 1)

结果:

| ID | SELLER | PRICE | AMOUNT |
--------------------------------
|  2 |    tom |   350 |    750 |
|  5 |  jerry |   500 |   1000 |