订购和分组

时间:2013-06-13 09:33:45

标签: mysql join group-by sql-order-by

我正在尝试显示我正在建设的商店的运费,数据库1中有三个表用于服务,即皇家邮政,运营商......,一个用于乐队即。英国,欧洲,Worldwide1等..和一个收费(数量=重量)

我有一个包含三个表的数据库,当从以下

加入时
+------------------+-----+-----------+-------+---------+---------------+----------+-------+-------------+
|       name       | qty | serviceID | basis | bandID | initial_charge | chargeID | price | total_price |
+------------------+-----+-----------+-------+---------+---------------+----------+-------+-------------+
| Collect in store |   0 |         3 |       |       1 | 3             | 0.00     | 2     | 0.00        |
| Royal mail       |   0 |         1 |     2 |       4 | 2.00          | 3        | 0.00  | 2.00        |
| Royal mail       |   1 |         1 |     2 |       4 | 2.00          | 4        | 1.00  | 3.00        |
| APC              |   0 |         2 |     1 |       1 | 0.00          | 6        | 5.95  | 5.95        |
+------------------+-----+-----------+-------+---------+---------------+----------+-------+-------------+

基本上我想要做的是(正如你所看到的)Royal Mail有两个条目,因为在连接表中有多个条目。我想要做的是显示两个皇家邮件条目中最高的(我最初尝试按service_id分组),同时还维护另外两个服务ID不同的服务

任何帮助都会很棒,因为这让我很生气。我觉得我已尝试过各种组合!

在下面的示例中,项目的数量(重量)为3千克

SELECT
    `service`.`name`,
    `charge`.`qty`,
    `service`.`serviceID`,
    `band`.`bandID`,
    `band`.`initial_charge`,
    `charge`.`chargeID`,
    `charge`.`price`,
    `band`.`initial_charge` + `charge`.`price` AS `total_price` 
FROM
    `delivery_band` AS `band` 
LEFT JOIN
    `delivery_charge` AS  `charge`
        ON 
            `charge`.`bandID` =  `band`.`bandID` 
        AND
            `charge`.`qty` <  '3'
LEFT JOIN
    `delivery_service` AS  `service`
        ON
            `service`.`serviceID` =  `band`.`serviceID` 
WHERE
    FIND_IN_SET(  '225',  `band`.`accepted_countries` ) 
AND
(
    `band`.`min_qty` >=  '3'
OR
    `band`.`min_qty` =  '0'
)
AND
(
    `band`.`max_qty` <=  '3'
OR
    `band`.`max_qty` =  '0'
)

delivery_service

+-----------+------------------+
| serviceID |       name       |
+-----------+------------------+
|         1 | Royal mail       |
|         2 | APC              |
|         3 | Collect in store |
+-----------+------------------+

delivery_band

+--------+-----------+-----------------+----------------+---------+---------+-------------------------------------------------------+
| bandID | serviceID |      name       | initial_charge | min_qty | max_qty |                  accepted_countries                   |
+--------+-----------+-----------------+----------------+---------+---------+-------------------------------------------------------+
|      1 |         2 | UK Mainland     | 0.00           |       0 |       0 | 225                                                   |
|      2 |         2 | UK Offshore     | 14.00          |       0 |       0 | 240                                                   |
|      3 |         3 | Bradford Store  | 0.00           |       0 |       0 | 225                                                   |
|      4 |         1 | UK              | 2.00           |       0 |       0 | 225                                                   |
|      5 |         2 | World wide      | 15.00          |       0 |       0 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20... |
|      6 |         1 | World wide Mail | 5.00           |       0 |       0 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20... |
+--------+-----------+-----------------+----------------+---------+---------+-------------------------------------------------------+

delivery_charge

+----------+--------+-----+-------+
| chargeID | bandID | qty | price |
+----------+--------+-----+-------+
|        1 |      2 |   0 | 5.00  |
|        2 |      3 |   0 | 0.00  |
|        3 |      4 |   0 | 0.00  |
|        4 |      4 |   1 | 1.00  |
|        5 |      4 |   5 | 3.00  |
|        6 |      1 |   0 | 5.95  |
|        7 |      1 |  10 | 10.95 |
|        8 |      2 |  10 | 14.00 |
|        9 |      5 |   0 | 0.00  |
|       10 |      5 |   3 | 5.00  |
|       11 |      5 |   6 | 10.00 |
|       12 |      5 |   9 | 15.00 |
|       13 |      6 |   0 | 0.00  |
|       14 |      6 |   2 | 5.00  |
|       15 |      6 |   4 | 10.00 |
|       16 |      6 |   6 | 15.00 |
+----------+--------+-----+-------+

当我尝试将费用表添加为子查询然后限制该查询时,它为所有费用表字段提供了NULL

如果我尝试以下查询:

SELECT
    `service`.`name`,
    `charge`.`qty`,
    `service`.`serviceID`,
    `band`.`bandID`,
    `band`.`initial_charge`,
    `charge`.`chargeID`,
    MAX( `charge`.`price` ) AS `price`,
    `band`.`initial_charge` + `charge`.`price` AS `total_price` 
FROM
    `delivery_band` AS `band` 
LEFT JOIN
    `delivery_charge` AS  `charge`
        ON 
            `charge`.`bandID` =  `band`.`bandID` 
        AND
            `charge`.`qty` <  '3'
LEFT JOIN
    `delivery_service` AS  `service`
        ON
            `service`.`serviceID` =  `band`.`serviceID` 
WHERE
    FIND_IN_SET(  '225',  `band`.`accepted_countries` ) 
AND
(
    `band`.`min_qty` >=  '3'
OR
    `band`.`min_qty` =  '0'
)
AND
(
    `band`.`max_qty` <=  '3'
OR
    `band`.`max_qty` =  '0'
)
GROUP BY
    `service`.`serviceID`

我得到了这个:

+------------------+-----+-----------+--------+----------------+----------+-------+-------------+
|       name       | qty | serviceID | bandID | initial_charge | chargeID | price | total_price |
+------------------+-----+-----------+--------+----------------+----------+-------+-------------+
| Royal mail       |   0 |         1 |      4 | 2.00           |        3 | 1.00  | 2.00        |
| APC              |   0 |         2 |      1 | 0.00           |        6 | 5.95  | 5.95        |
| Collect in store |   0 |         3 |      3 | 0.00           |        2 | 0.00  | 0.00        |
+------------------+-----+-----------+--------+----------------+----------+-------+-------------+

原则上看起来很好,直到你意识到chargeID = 3的价格为0.00而且该表显示的是1.00的价格,因此价值似乎已经解除了分离

1 个答案:

答案 0 :(得分:0)

  

我想要做的是显示两个皇家邮件条目中最高的

您可以使用MAX获取给定列的最大值,例如

SELECT … MAX(charge.price) … FROM …

如果您绝对需要其他列(例如charge.chargeID)匹配,那么事情会变得非常复杂很多。因此,请确保您确实需要它。有关此类查询背后的一般概念的详细信息,请仔细查看Select one value from a group based on order from other columns。通过this answer调整@RichardTheKiwi,我想出了以下查询:

SELECT s.name,
       c.qty,
       s.serviceID,
       b.bandID,
       b.initial_charge,
       c.chargeID,
       c.price,
       b.initial_charge + c.price AS total_price
FROM delivery_band AS b,
     delivery_service AS s,
    (SELECT chargeID, price, qty,
            @rowctr := IF(bandId = @lastBand, @rowctr+1, 1) AS rowNumber,
            @lastBand := bandId AS bandId
     FROM (SELECT @rowctr:=0, @lastBand:=null) init,
          delivery_charge
     WHERE qty < 3
     ORDER BY bandId, price DESC
    ) AS c
WHERE FIND_IN_SET(225, b.accepted_countries)
  AND (b.min_qty >= 3 OR B.min_qty = 0)
  AND (b.max_qty <= 3 OR B.max_qty = 0)
  AND s.serviceID = b.serviceID
  AND c.bandID = b.bandID
  AND c.rowNumber = 1

请参阅this fiddle了解相应的输出。请注意,我只进行内部查询,而不是左查询,因为这对于有问题的查询来说似乎已经足够了,并且使事情更具可读性,因此您可以专注于重要部分,即涉及rowNumber的部分。这个想法是子查询为相同波段的项生成行号,将它们重置为下一个波段。当您只选择rowNumber为1的行时,您只能获得最高价格,以及与该相关联的所有其他列。