I have a list of inventory units and sale transactions that I want to, (1) join by unit SKU, and (2) associate ONE transaction to ONE inventory unit in first-in-first-out order by date. I'm having trouble with the second part.
The best I can come up with is:
SELECT `units`.`unit_date`, `units`.`unit_id`, `trans`.`tran_date`, `trans`.`tran_id`, `units`.`unit_sku` FROM `units`
INNER JOIN `trans`
ON `trans`.`unit_sku` = `units`.`unit_sku`
GROUP BY `trans`.`tran_id`, `trans`.`unit_sku`
ORDER BY `units`.`unit_date` asc, `trans`.`tran_date` asc
;
units
table:
unit_date | unit_id | unit_sku
2015-06-01 | 1 | U1KLM
2015-06-02 | 2 | U1KLM
2015-06-03 | 3 | U2QRS
2015-06-04 | 4 | U2QRS
2015-06-05 | 5 | U1KLM
trans
table:
tran_date | tran_id | unit_sku
2015-06-11 | A | U2QRS
2015-06-12 | B | U1KLM
2015-06-13 | C | U1KLM
2015-06-14 | D | U2QRS
2015-06-15 | E | U1KLM
The desired result is one tran_id
to be joined to one unit_id
of the unit_sku
by earliest-to-latest order of unit_date
:
unit_date | unit_id | tran_date | tran_id | unit_sku
2015-06-01 | 1 | 2015-06-12 | B | U1KLM
2015-06-02 | 2 | 2015-06-13 | C | U1KLM
2015-06-03 | 3 | 2015-06-11 | A | U2QRS
2015-06-04 | 4 | 2015-06-14 | D | U2QRS
2015-06-05 | 5 | 2015-06-15 | E | U1KLM
The query (undesired) result joins tran_id
only to the unit_id
of the earliest occurrence of unit_sku
:
unit_date | unit_id | tran_date | tran_id | unit_sku
2015-06-01 | 1 | 2015-06-12 | B | U1KLM
2015-06-01 | 1 | 2015-06-13 | C | U1KLM
2015-06-01 | 1 | 2015-06-15 | E | U1KLM
2015-06-03 | 3 | 2015-06-11 | A | U2QRS
2015-06-03 | 3 | 2015-06-14 | D | U2QRS
Any ideas on how to do get the desired result? In this setup, only unit_date
and tran_date
are sortable; the rest are randomly generated.
Repro script:
DROP TEMPORARY TABLE IF EXISTS `units`;
DROP TEMPORARY TABLE IF EXISTS `trans`;
CREATE TEMPORARY TABLE `units` (`unit_date` date, `unit_id` char(1) , `unit_sku` char(5), PRIMARY KEY(`unit_id`));
CREATE TEMPORARY TABLE `trans` (`tran_date` date, `tran_id` char(1) , `unit_sku` char(5), PRIMARY KEY(`tran_id`));
INSERT INTO `units` (`unit_date`, `unit_id`, `unit_sku`) VALUES
('2015-06-01', '1', 'U1KLM')
, ('2015-06-02', '2', 'U1KLM')
, ('2015-06-03', '3', 'U2QRS')
, ('2015-06-04', '4', 'U2QRS')
, ('2015-06-05', '5', 'U1KLM')
;
INSERT INTO `trans` (`tran_date`, `tran_id`, `unit_sku`) VALUES
('2015-06-11', 'A', 'U2QRS')
, ('2015-06-12', 'B', 'U1KLM')
, ('2015-06-13', 'C', 'U1KLM')
, ('2015-06-14', 'D', 'U2QRS')
, ('2015-06-15', 'E', 'U1KLM')
;
SELECT `units`.`unit_date`, `units`.`unit_id`, `trans`.`tran_date`, `trans`.`tran_id`, `units`.`unit_sku` FROM `units`
INNER JOIN `trans`
ON `trans`.`unit_sku` = `units`.`unit_sku`
GROUP BY `trans`.`tran_id`, `trans`.`unit_sku`
ORDER BY `units`.`unit_date` asc, `trans`.`tran_date` asc
;
I believe this is what you're looking for: (This is assuming that 1 to 1 relationship)
SET @UNITRN := 0;
SET @TRANSRN :=0;
SELECT A.`unit_date`, A.`unit_id`, B.`tran_date`, B.`tran_id`, A.`unit_sku` FROM (SELECT @UNITRN := @UNITRN + 1 AS ROWNUM, UNIT_DATE, UNIT_ID, UNIT_SKU FROM UNITS ORDER BY UNIT_SKU, UNIT_DATE ASC) A
JOIN (SELECT @TRANSRN := @TRANSRN + 1 AS ROWNUM, TRAN_DATE, TRAN_ID, UNIT_SKU FROM TRANS ORDER BY UNIT_SKU, TRAN_DATE ASC) B
ON A.UNIT_SKU = B.UNIT_SKU
AND A.ROWNUM = B.ROWNUM
ORDER BY A.UNIT_DATE ASC
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.