开发者

MySQL Problem writing query

I currently have a table which holds catalog information with the following fields:

catalog, pr开发者_如何学Pythonice, product_id, size, pack_size, stock_level

A product can appear in the catalog up to 30 times (the same product with a different size and/or in a different pack size must have a unique catalog_id)

I now want to display a table which has sizes down the left, pack sizes across the top and prices as the data, but don't know how to write the query.


SELECT 
  ci.size
  ,sum(if(ci.pack_size=1,ci.price,null)) as pack_size1
  ,sum(if(ci.pack_size=2,ci.price,null)) as pack_size2
  ,sum(if(ci.pack_size=3,ci.price,null)) as pack_size3
  ,sum(if(ci.pack_size=4,ci.price,null)) as pack_size4
FROM catalog_info ci
WHERE ci.product_id = 345
GROUP BY ci.size -- WITH ROLLUP

If you uncomment the "WITH ROLLUP" MySQL will add an extra grant total row at the end.

Same query for multiple products.

SELECT 
  ci.product_id
  ,ci.size
  ,sum(if(ci.pack_size=1,ci.price,null)) as pack_size1
  ,sum(if(ci.pack_size=2,ci.price,null)) as pack_size2
  ,sum(if(ci.pack_size=3,ci.price,null)) as pack_size3
  ,sum(if(ci.pack_size=4,ci.price,null)) as pack_size4
FROM catalog_info ci
WHERE ci.product_id BETWEEN 1 AND 100
GROUP BY ci.product_id ASC, ci.size DESC -- WITH ROLLUP

Note that with rollup you cannot add an order by clause, but you can effect the implicit ordering in the group clause (ASC, DESC) as shown above. Uncomment the with rollup to add a grant total row.


So, you're looking to get a group of all red widgets, including:

  • Small red widget
  • Small red widget (pack of 5)
  • Medium red widget
  • Medium red widget (pack of 5)
  • Large red widget
  • Large red widget (pack of 5)

They all have separate IDs. If you can guarantee that the IDs will always be in a consecutive range, you could do something like

SELECT * FROM products WHERE product_id BETWEEN 45 AND 50

However, maintaining the consistency of the ID numbers would be a pain in the butt. The next approach would be to just add a whole bunch of OR clauses:

SELECT * FROM products WHERE 
   product_id = 45
   OR product_id = 46
   OR product_id = 47
   OR product_id = 87
   OR product_id = 93

But that again wouldn't solve the problem that you don't know the numbers of all the products in a group.

So you're going to need to alter your database in one of two ways.

Method 1: alter the products table to add a new column that contains an ID number for the family of product. Thus:

ALTER TABLE products ADD COLUMN `family_id` INT(10) NOT NULL DEFAULT 0 AFTER product_id

Then manually go through and add the same family_id to groups of products:

UPDATE products SET family_id = 1 WHERE product_id = 45;
UPDATE products SET family_id = 1 WHERE product_id = 46;
UPDATE products SET family_id = 1 WHERE product_id = 47;
UPDATE products SET family_id = 1 WHERE product_id = 48;

So that you can then get them all out with a simple query like this:

SELECT * FROM products WHERE family_id = 1;

Method 2: is to create a second table to track relationships between individual products and product families:

CREATE TABLE `families` (
`relationship_id` INT(10) PRIMARY KEY AUTO_INCREMENT,
`family_id` INT(10) NOT NULL DEFAULT 0,
`product_id` INT(10) NOT NULL DEFAULT 0
);

Then put all your relationship data in there:

INSERT INTO families (family_id, product_id) VALUES (1, 45);
INSERT INTO families (family_id, product_id) VALUES (1, 46);
INSERT INTO families (family_id, product_id) VALUES (1, 47);
INSERT INTO families (family_id, product_id) VALUES (1, 87);

And you can get it out again with a join:

SELECT p.* FROM products p, families f 
   WHERE p.product_id = f.product_id 
   AND family_id = 1;

I would tend to prefer the second solution personally, but either way will work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜