2012-04-05 93 views
1

我需要帮助MySQL查询。我有三个表:MySQL一对多关系:GROUP_CONCAT或JOIN或两者兼而有之?

`product_category` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(255) NOT NULL, 
PRIMARY KEY (`id`) 
); 

`order_products` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(255) NOT NULL, 
    `qty` int(11) NOT NULL, 
    `unit_price` decimal(11,2) NOT NULL, 
    `category` int(11) NOT NULL, 
    `order_id` int (11) NOT NULL, 
    PRIMARY KEY (`id`) 
); 

`orders` (
    `id` int(11) NOT NULL auto_increment, 
    `date` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
); 

我有这样计算的所有订单按产品类别的分类汇总查询(在一定的日期范围)。它是这样的:

SELECT 
    SUM(op.unit_price * op.qty) as amt, 
    c.name as category_name 
FROM 
    order_products op, 
    product_category c, 
    orders o 
WHERE 
    op.category = c.id 
AND 
    op.order_id = o.id 
AND 
    o.date > 'xxxxxxx' 
GROUP BY 
    c.id 

这个伟大的工程,但现在我想个别产品及其小计添加到每一行,使我得到这样一个结果:

c.name|amt|op.name (1) - op.subtotal (1), op.name (2), op.subtotal (2), etc.... 

我想通了使用GROUP_CONCAT我能得到的名称显示出来很容易地通过添加:

GROUP_CONCAT(op.name) as product_name 

到SELECT子句,但对我的生活我无法弄清楚如何让小计每个公关请在产品名称旁边显示。我有一种感觉,它涉及到嵌套在GROUP_CONCAT中的连接或CONCAT的组合,但我没有尝试过任何工作。有任何想法吗?

@piotrm有一个想法,好像它应该工作(下同),但由于某种原因,它返回下列信息:只要我拿出s.subtotal从它拉原来的SELECT子句

SELECT `subtotals` 
FROM `product_category` 
WHERE `c`.`category_name` = 'Fragrance'AND.`amt` = '23164.50'AND.`subtotals` = CAST( 0x6c6f76656c696c7920454454202d203631302e30302c20466f72657665726c696c79202e313235206f7a2045445020726f6c6c657262616c6c202d20313831372e35302c20666f72657665726c696c79206361636865706f74202d2039302e30302c20666f72657665726c696c7920312f38206f756e63652070617266756d206f696c20726f6c6c657262616c6c202d20313833302e30302c20666f72657665726c696c792070657266756d696e6720626f6479206c6f74696f6e202d203938312e30302c20666f72657665726c696c7920332e34206f756e6365206561752064652070617266756d207370726179202009202d203535382e30302c20666f72657665726c696c79205363656e74656420566f746976652043616e646c65202d203132302e30302c20454450202620426f6f6b20736574202d203334332e30302c20666f72657665726c696c7920332e34206f756e6365206561752064652070617266756d207370726179202d2031363831352e3030 AS 
BINARY) ; 

正确的产品名称。 JOIN查询将产品正确地拉出与其关联的category_id和小计。我不能把这两个人放在一起,不要在这里创造这个烂摊子。任何其他想法?

解决方案

@ piotrm的查询基本上是正确的,除了GROUP_CONCAT正在寻找字符串的集合。所以最终的查询是这样的:

SELECT c.name AS category_name, 
     SUM(s.subtotal) AS amt, 
     GROUP_CONCAT(CONCAT(s.name, ' - ', cast(s.subtotal as char)) SEPARATOR ', ')       AS subtotals 
FROM 
     product_category c 
JOIN 
    (SELECT op.category, op.name, sum(op.qty*op.unit_price) AS subtotal 
FROM order_products op 
JOIN orders o ON o.id = op.order_id 
WHERE o.date > '0' 
GROUP BY op.category, op.name) s 
ON s.category = c.id 
GROUP BY c.name 

回答

0

从查询猜测也有在你的order_productsorder_id场你没在表定义中提及。然后,您的查询应该是这样的:

SELECT c.name AS category_name, 
      SUM(s.subtotal) AS amt, 
      GROUP_CONCAT(CONCAT(s.name, ' - ', s.subtotal) SEPARATOR ', ') AS subtotals 
FROM 
    product_category c 
JOIN 
    (SELECT op.category, op.name, sum(op.qty*op.unit_price) AS subtotal 
    FROM order_products op 
    JOIN orders o ON o.id = op.order_id 
    WHERE o.date > '2012-03-31' 
    GROUP BY op.category, op.name) s 
    ON s.category = c.id 
GROUP BY c.name 

你的数据库架构是相当怪异虽然,订单表看起来可能被删除,该日期搬到order_products,因为每一个order_products行你必须参考订单表。通常情况下,这是另一种方式 - 订单表中的product_id字段引用的每个产品都有很多订单。另外日期列中的订单是类型varchar - 为什么不是日期或日期时间?

+0

order_products存储与订单相关的产品(一对多关系,因为订单可以有很多产品)。日期列是varchar,因为我在那里存储unix时间戳,而不是日期时间。你的回答看起来应该可行,我会修改原始帖子以显示发生了什么。 – 2012-04-05 22:25:07

+0

知道了!你的SQL是正确的,但GROUP_CONCAT不能在动态列上工作。我会在原帖中发布解决方案,但我将你的答案标记为正确,因为如果没有它,我不会得到答案。谢谢! – 2012-04-06 01:35:03

0

尝试:

SELECT 
    SUM(op.unit_price * op.qty) as amt, 
    c.name as category_name, 
    group_concat(concat(op.name, '-', op.qty, ',' , 
       op.unit_price*op.qty) separator '|') 
    ... 
+0

谢谢 - 我已经尝试过,但它不起作用。它在该列中返回一个“blob”,其数据如下:'code' SELECT'subtotal' FROM'order_products' WHERE.'amt' ='##。###' AND'c'.'category_name' ='' [分类名称]'; – 2012-04-05 20:06:44

+0

btw你应该由c.id和c.name组成 – 2012-04-05 20:13:33

+0

不幸的是,也没有做到这一点。谢谢! – 2012-04-05 20:42:32

相关问题