Reputation: 1888
I need to record the number of items requested and issued against each item every day. The purchase_doc
table is:
The requested_items
table contains item requested as follows:
The movement
table contains item requested as follows:
The need output (data to be inserted) is:
One way of doing this is to fetch items issued and requested from the first 2 queries, and then build an array of items issued and requested against each item id, and then insert these values in the daily_movement table, like this:
SELECT n.item_id AS n__item_id, SUM(n.qty) AS qty
FROM requested_items n LEFT JOIN purchase_doc doc ON n.doc_id = doc.id
WHERE (doc.type = 'Item Request' AND doc.created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR))
GROUP BY n.item_id
SELECT n.item_id AS item_id, SUM(n.qty) AS qty
FROM movement n LEFT JOIN purchase_doc doc ON n.doc_id = doc.id
WHERE (doc.type = 'Store Issue' AND doc.created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR))
GROUP BY n.item_id
From these and other SELECTs, I need to insert a single row per item per day containing the qty of requests, issues, etc for this item in this fashion:
INSERT INTO daily_movement date, item_id, requested_qty, issued_qty VALUES ( NOW(), 23, 4, 5), ( NOW(), 25, 5, 5), ( NOW(), 113, 6, 8);
But there will be too many SELECTs (since I also need other activities performed per item), followed by an insert.
My question is: Is it possible to do this via a single SELECT ... INSERT statement. If not, can somebody suggest a more elegant way of doing this
Upvotes: 0
Views: 2026
Reputation: 88647
I'm thinking this, but it might be over-simplified:
INSERT INTO `daily_movement`
(`date`, `item_id`, `requested_qty`, `issued_qty`)
SELECT NOW(), `r`.`item_id`, SUM(`r`.`qty`), SUM(`m`.`qty`)
FROM `purchase_doc` `d`
JOIN `requested_items` `r`
ON `r`.`doc_id` = `d`.`id`
LEFT JOIN `movement` `m`
ON `m`.`doc_id` = `d`.`id`
WHERE
(`d`.`type` = 'Item Request' OR `d`.`type` = 'Store Issue')
AND
`d`.`created_at` > DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY `r`.`item_id`
EDIT
This is my final answer, with a nasty UNION
to get around MySQL's lack of FULL OUTER JOIN
:
INSERT INTO `daily_movement`
(`date`, `item_id`, `week_no`, `requested_qty`, `issued_qty`)
SELECT *
FROM (
(
SELECT COALESCE(`r`.`item_id`, `a`.`item_id`) AS `item_id`, CURDATE() AS `date`, NULL AS `week_no`, SUM(`r`.`qty`) AS `requests`, COALESCE(`a`.`issued`, 0) AS `issued`
FROM `purchase_doc` `d`
LEFT JOIN `requested_items` `r`
ON `r`.`doc_id` = `d`.`id`
LEFT JOIN (
SELECT `m`.`item_id`, SUM(`m`.`qty`) AS `issued`
FROM `purchase_doc` `d`
JOIN `movement` `m`
ON `m`.`doc_id` = `d`.`id`
WHERE `d`.`type` = 'Store Issue'
AND `d`.`created_at` > DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY `m`.`item_id`
) `a`
ON `a`.`item_id` = `r`.`item_id`
WHERE `d`.`type` = 'Material Requisition'
AND `d`.`created_at` > DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY `r`.`item_id`
) UNION DISTINCT (
SELECT COALESCE(`m`.`item_id`, `a`.`item_id`) AS `item_id`, CURDATE() AS `date`, NULL AS `week_no`, COALESCE(`a`.`requests`, 0) AS `requests`, SUM(`m`.`qty`) AS `issued`
FROM `purchase_doc` `d`
LEFT JOIN `movement` `m`
ON `m`.`doc_id` = `d`.`id`
LEFT JOIN (
SELECT `r`.`item_id`, SUM(`r`.`qty`) AS `requests`
FROM `purchase_doc` `d`
JOIN `requested_items` `r`
ON `r`.`doc_id` = `d`.`id`
WHERE `d`.`type` = 'Material Requisition'
AND `d`.`created_at` > DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY `r`.`item_id`
) `a`
ON `a`.`item_id` = `m`.`item_id`
WHERE `d`.`type` = 'Store Issue'
AND `d`.`created_at` > DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY `m`.`item_id`
)
ORDER BY `item_id`
) `u`
http://sqlfiddle.com/#!2/3923d/13
Upvotes: 1
Reputation: 121912
You can use a query like this -
edited:
INSERT INTO daily_movement(date, item_id, requested_qty, issued_qty)
SELECT i.item_id, SUM(ri.qty) requested_qty, SUM(m.qty) issued_qty FROM
(SELECT item_id FROM requested_items UNION SELECT item_id FROM movement) i
LEFT JOIN (
SELECT n.item_id, n.qty
FROM requested_items n LEFT JOIN purchase_doc doc ON n.doc_id = doc.id
WHERE doc.type = 'Item Request' AND doc.created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)
) ri
ON ri.item_id = i.item_id
LEFT JOIN (
SELECT n.item_id, n.qty
FROM movement n LEFT JOIN purchase_doc doc ON n.doc_id = doc.id
WHERE doc.type = 'Store Issue' AND doc.created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)
) m
ON m.item_id = i.item_id
GROUP BY
i.item_id;
Upvotes: 0