2

OK、私はこの非常に複雑な問題に直面しています。私は MySQL の達人ではないので、それについてあなたの意見が絶対に必要です。

以下のコードを使用して作成されたデータベースがあるとしましょう (すべてのテーブルを貼り付けないようにするために、絶対に必要なテーブルだけの作成コードを貼り付けています)。

DROP TABLE IF EXISTS `Jeweller`.`Orders`;
CREATE TABLE `Jeweller`.`Orders` (
  `id` int(11) unsigned NOT NULL,
  `date` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `Jeweller`.`Product_categories`;
CREATE TABLE `Jeweller`.`Product_categories` (
  `id` int(11) unsigned NOT NULL,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `Jeweller`.`Product_orders`;
CREATE TABLE `Jeweller`.`Product_orders` (
  `order_id` int(11) unsigned NOT NULL,
  `product_id` int(11) unsigned NOT NULL,
  `quantity` int(11),
  `value` float,
  FOREIGN KEY (`order_id`) REFERENCES `Jeweller`.`Orders`(`id`),
  FOREIGN KEY (`product_id`) REFERENCES `Jeweller`.`Products`(`id`),
  CHECK (`quantity`>0),
  CHECK (`value`>0)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `Jeweller`.`Product_returns`;
CREATE TABLE `Jeweller`.`Product_returns` (
  `sale_id` int(11) unsigned NOT NULL,
  `product_id` int(11) NOT NULL,
  `date` date DEFAULT NULL,
  `quantity` int(11),
  `value` float,
  FOREIGN KEY (`sale_id`) REFERENCES `Jeweller`.`Sales`(`id`),
  FOREIGN KEY (`product_id`) REFERENCES `Jeweller`.`Products`(`id`),
  CHECK (`quantity`>0),
  CHECK (`value`>0)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `Jeweller`.`Product_sales`;
CREATE TABLE `Jeweller`.`Product_sales` (
  `sale_id` int(11) unsigned NOT NULL,
  `product_id` int(11) NOT NULL,
  `quantity` int(11),
  `value` float,
  FOREIGN KEY (`sale_id`) REFERENCES `Jeweller`.`Sales`(`id`),
  FOREIGN KEY (`product_id`) REFERENCES `Jeweller`.`Products`(`id`),
  CHECK (`quantity`>0),
  CHECK (`value`>0)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `Jeweller`.`Products`;
CREATE TABLE `Jeweller`.`Products` (
  `id` int(11) unsigned NOT NULL,
  `product_category_id` int(11) NOT NULL,
  `seller_id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL,
  `description` text,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`product_category_id`) REFERENCES `Jeweller`.`Product_categories`(`id`),
  FOREIGN KEY (`seller_id`) REFERENCES `Jeweller`.`Sellers`(`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `Jeweller`.`Sales`;
CREATE TABLE `Jeweller`.`Sales` (
  `id` int(11) unsigned NOT NULL,
  `date` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ここで、 Profitを次のように定義するとします。

  • Sales - Returns - Orders

取得するクエリをどのように処理しますか :

月ごとの利益 AND product_category、2013 年のみ。


テスト目的で、完全なDB 作成コードとDB 作成コード(いくつかのデモ データを含む) を次に示します。( SQLFiddle リンク)


PS

  • 実際のコードは少し異なります (上記は単なる例ですが、100% 忠実なものです)。

  • 何度か試みた後、2013年の売上/注文などをフィルタリングすることができました...製品ごとに利益を得ることができました(ただし、無限joinのs、left outer joinsなどを要しました...笑)...しかし、これはるかに複雑に見えます。何か案は?

4

2 に答える 2

1

これがあなたのスキーマの概算です...

DROP TABLE IF EXISTS orders;
CREATE TABLE orders 
( order_id int(11) unsigned NOT NULL auto_increment
, date date DEFAULT NULL
, PRIMARY KEY (order_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO orders VALUES
(NULL,'2013-01-01'),
(NULL,'2013-01-01'),
(NULL,'2013-02-02'),
(NULL,'2013-02-03'),
(NULL,'2013-03-05'),
(NULL,'2013-06-07');

DROP TABLE IF EXISTS product_orders;
CREATE TABLE product_orders 
( order_id int unsigned NOT NULL
, product_id int unsigned NOT NULL
, quantity int NOT NULL DEFAULT 1
, value DECIMAL(5,2)
, PRIMARY KEY(order_id,product_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO product_orders VALUES
(1,101,1,100),
(1,102,1,50),
(2,101,2,200),
(3,101,1,100),
(4,102,2,100),
(4,103,3,150),
(5,104,1,300),
(6,102,1,50),
(6,103,2,100),
(6,104,1,300);

DROP TABLE IF EXISTS product_returns;
CREATE TABLE product_returns 
( sale_id int unsigned NOT NULL
, product_id int NOT NULL
, date date DEFAULT NULL
, quantity int NOT NULL DEFAULT 1
, value DECIMAL(5,2)
, PRIMARY KEY(sale_id,product_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO product_returns VALUES
(21,101,'2013-01-04',2,200),
(22,102,'2013-03-06',1,50),
(22,103,'2013-05-08',1,50),
(23,104,'2013-06-09',1,300);


DROP TABLE IF EXISTS product_sales;
CREATE TABLE product_sales 
( sale_id int unsigned NOT NULL
, product_id int NOT NULL
, quantity int NOT NULL
, value DECIMAL(5,2)
, PRIMARY KEY(sale_id,product_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO product_sales VALUES
(20,101,1,100),
(20,102,1,50),
(21,101,3,300),
(22,101,1,100),
(22,102,2,100),
(22,103,1,50),
(23,103,2,100),
(23,104,2,600);


DROP TABLE IF EXISTS products;
CREATE TABLE products 
( product_id int unsigned NOT NULL AUTO_INCREMENT
, product_category_id int NOT NULL
, name varchar(100) NOT NULL
, description text NULL
, PRIMARY KEY (product_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO products VALUES
(101,1,'donuts','Mmm, donuts'),
(102,2,'buzz Cola','Mmm, donuts'),
(103,2,'duff beer','Can\'t get enough'),
(104,1,'Krusty-O\'s','Yum, yum');

DROP TABLE IF EXISTS sales;
CREATE TABLE sales
( sale_id int NOT NULL
, date date DEFAULT NULL
, PRIMARY KEY (sale_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO sales VALUES
(20,'2013-01-12'),
(21,'2013-02-15'),
(22,'2013-03-17'),
(23,'2013-05-18');

...そして可能なクエリ...

SELECT p.product_category_id
     , MONTH(date) month
     , SUM(value) profit
  FROM 
     ( SELECT product_id,value, date 
         FROM product_sales ps
         JOIN sales s
           ON s.sale_id = ps.sale_id
        UNION ALL
       SELECT product_id,value*-1,date FROM product_returns
        UNION ALL
       SELECT product_id,value*-1,date
         FROM product_orders po
         JOIN orders o
           ON o.order_id = po.order_id
     ) x
  JOIN products p
    ON p.product_id = x.product_id
 WHERE YEAR(date) = 2013
 GROUP
    BY p.product_category_id
     , MONTH(date);

+---------------------+-------+---------+
| product_category_id | month | profit  |
+---------------------+-------+---------+
|                   1 |     1 | -400.00 |
|                   1 |     2 |  200.00 |
|                   1 |     3 | -200.00 |
|                   1 |     5 |  600.00 |
|                   1 |     6 | -600.00 |
|                   2 |     1 |    0.00 |
|                   2 |     2 | -250.00 |
|                   2 |     3 |  100.00 |
|                   2 |     5 |   50.00 |
|                   2 |     6 | -150.00 |
+---------------------+-------+---------+

...そして同じのsqlfiddle:http://www.sqlfiddle.com/#!2/22a1d/1

于 2013-06-11T12:37:57.680 に答える