mysql GROUB BY的想法

时间:2017-08-06 07:46:30

标签: mysql

我有以下情况:有1个带书籍的表和两对表(HD / IT),其中销售订单和采购订单交易通过销售订单ID连接。 表格结构如下:

CREATE TABLE `books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `isbn` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `it_id` int(11) NOT NULL,
  `kind` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `books` (`id`, `isbn`, `it_id`, `kind`) VALUES
(1, '12345',    1,  1),
(2, '12345',    1,  2),
(3, '67890',    2,  1),
(4, '1111111',  2,  2);

CREATE TABLE `porders_hd` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dt` date NOT NULL,
  `so_id` int(11) DEFAULT NULL,
  `customer` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `porders_hd` (`id`, `dt`, `so_id`, `customer`) VALUES
(1, '2017-07-02',   1,  1),
(2, '2017-08-03',   NULL,   3);

CREATE TABLE `porders_it` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `hd_id` int(11) NOT NULL,
  `isbn` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `dscr` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `qty` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `porders_it` (`id`, `hd_id`, `isbn`, `dscr`, `qty`) VALUES
(1, 1,  '12345',    'Book 1',   1),
(2, 2,  '1111111',  'Book 2',   1);

CREATE TABLE `sorders_hd` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dt` date NOT NULL,
  `customer` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `sorders_hd` (`id`, `dt`, `customer`) VALUES
(1, '2017-07-01',   1),
(2, '2017-08-01',   2);

CREATE TABLE `sorders_it` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `hd_id` int(11) NOT NULL,
  `isbn` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `dscr` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `qty` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `sorders_it` (`id`, `hd_id`, `isbn`, `dscr`, `qty`) VALUES
(1, 1,  '12345',    'Book 1',   1),
(2, 2,  '67890',    'Book 2',   1);

总结如下: * 1采购订单中存在的销售订单(#1)(#1) * 1销售订单(#2)仍在等待中 * 1没有销售订单创建的采购订单(#2)

我希望能够获取每本书的所有销售和采购订单的isbn,并且连接的SO和PO必须在同一行。输出必须如下所示:

so_id   so_date     po_id   po_date     isbn    dscr
NULL    NULL        2       2017-08-03  1111111 Book 2
1       2017-07-01  1       2017-07-02  12345   Book 1
2       2017-08-01  NULL    NULL        67890   Book 3

我尝试使用如下所示的查询抓取行:

SELECT 
GROUP_CONCAT(so_id) so_id,
GROUP_CONCAT(so_date) so_date,
GROUP_CONCAT(po_id) po_id,
GROUP_CONCAT(po_date) po_date,
isbn,
dscr
FROM (

SELECT
hd.so_id        so_id,
NULL        so_date,
hd.id   po_id,
hd.dt po_date,
bk.isbn,
it.dscr
            FROM porders_hd hd,
                 porders_it it,
                 books bk
           WHERE it.hd_id = hd.id
             AND bk.isbn  = it.isbn
             AND kind = 2
UNION
SELECT
hd.id   so_id,
hd.dt so_date,
NULL        po_id,
NULL        po_date,
bk.isbn,
it.dscr
            FROM sorders_hd hd,
                 sorders_it it,
                 books bk
           WHERE it.hd_id = hd.id
             AND bk.isbn  = it.isbn
             AND kind = 1

) as table1
 GROUP BY isbn, so_id, po_id

但由于缺少信息,我得到以下结果:

so_id   so_date     po_id   po_date     isbn    dscr
NULL    NULL        2       2017-08-03  1111111 Book 2
1       2017-07-01  NULL    NULL        12345   Book 1
1       NULL        1       2017-07-02  12345   Book 1
2       2017-08-01  NULL    NULL        67890   Book 3

任何想法我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:0)

我认为这就是你所追求的,但我可以从你的代码中找出My.Computer.Registry.GetValue("registry key here", "Key to delete", Nothing) Is Nothing的作用。但是这里有一个查询,对于每本书,获取相关的po行项目,找到相应的so行项目并加入标题行,以便日期可用。请注意我的假设,即销售订单不能与相应的采购订单一起存在。

kind

您可以规范化表格,以便不需要重复descr,也可以使用其他表格中的book.id而不是isbn。

答案 1 :(得分:0)

我添加了一个新的答案,因为前一个和评论是说明性的。基于该讨论,这需要一个FULL OUTER JOIN,它必须由mysql中的UNION ALL模拟(这可能是OP最初尝试的)。

这是我的新代码,考虑到这一点:

SELECT sorders_hd.id as so_id, sorders_hd.dt as so_dt,
porders_hd.id as po_id, porders_hd.dt as po_dt,
books.isbn, porders_it.dscr
from books 
left outer join porders_it on porders_it.isbn=books.isbn 
join porders_hd on porders_hd.id=porders_it.hd_id 
left outer join sorders_it on sorders_it.isbn=books.isbn and sorders_it.hd_id=porders_hd.so_id
left outer join sorders_hd on sorders_hd.id=sorders_it.hd_id
where books.kind=2

UNION ALL 

SELECT sorders_hd.id as so_id, sorders_hd.dt as so_dt,
porders_hd.id as po_id, porders_hd.dt as po_dt,
books.isbn, sorders_it.dscr
from books 
left outer join sorders_it on sorders_it.isbn=books.isbn 
join sorders_hd on sorders_hd.id=sorders_it.hd_id
left outer join porders_it on porders_it.isbn=books.isbn
left outer join porders_hd on porders_hd.id=porders_it.hd_id and porders_hd.so_id=sorders_hd.id
where porders_hd.id is null and books.kind=1;

输出结果为:

so_id   so_dt       po_id   po_dt        isbn     dscr
1       2017-07-01  1       2017-07-02   12345    Book 1
(null)  (null)      2       2017-08-03   1111111  Book 2
2       2017-08-01  (null)  (null)       67890    Book 2

请参阅SqlFiddle

"技巧"是使用union all和两个查询之一,不包括链接双方的记录(以获得FULL OUTER JOIN的'右侧)

+1到OP用于提供DDL和样本数据!

我同意数据模型可以重做,并且可以标准化。当销售订单和采购订单匹配时(其中一个被忽略),现有模型仍至少存在重复账簿记录的问题。在我看来,一个改进是拥有一个主书籍清单,并在porders_it和sorders_it中包含该表的id(或isbn,如果这是主键),并删除当前的书籍表。