MySql: get data from two tables with grouping by Date - mysql

I have two table with almost same columns, i want to merge them and grouped by date
Table1: order_payments_detail
| payment_by | amount( as Debit in result) | added_on |
| Ali | 1000 | 2014-09-21 |
| Aslam | 2000 | 2014-09-25 |
| Akram | 4000 | 2014-09-28 |
Table2: orders
| cust_name | amount( as credit in result)| added_on |
| Shop1 | 1000 | 2014-09-22 |
| Shop2 | 2000 | 2014-09-26 |
| Shop3 | 4000 | 2014-09-29 |
Result will be like this
| particulars| debit | credit | added_on |
| Ali | 1000 | null | 2014-09-21 |
| Shop1 | null | 1000 | 2014-09-22 |
| Aslam | 2000 | null | 2014-09-25 |
| Shop2 | null | 2000 | 2014-09-26 |
| Akram | 4000 | null | 2014-09-28 |
| Shop3 | null | 4000 | 2014-09-29 |

You can readily do this with union all:
select payment_by, amount as debit, NULL as credit, added_on
from order_payments_detail
union all
select cust_name, NULL, amount, added_on
from orders
order by added_on;
By "grouped by date", I assume that you really mean "ordered by date".

Related

How to subtract the sum of value using left join?

I have two tables orders and customers:
select * from orders;
+------+---------------------+-------------+--------+
| oid | date | customer_id | amount |
+------+---------------------+-------------+--------+
| 102 | 2009-10-08 00:00:00 | 4 | 300 |
| 100 | 2009-10-08 00:00:00 | 3 | 15000 |
| 101 | 2008-10-08 00:00:00 | 2 | 1300 |
| 105 | 2010-10-08 00:00:00 | 1 | 400 |
| 106 | 2014-12-23 00:00:00 | 3 | 300 |
+------+---------------------+-------------+--------+
select * from customers;
+------+--------+------+-----------+----------+
| id | name | age | address | salary |
+------+--------+------+-----------+----------+
| 1 | ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | khilan | 25 | delhi | 1500.00 |
| 3 | muffy | 22 | bhopal | 8500.00 |
| 4 | suresh | 48 | mumbai | 24000.00 |
| 1 | ramesh | 32 | Ahmedabad | 300.00 |
| 5 | akil | 21 | madurai | 1000.00 |
| 6 | rajesh | 22 | delhi | 5000.00 |
+------+--------+------+-----------+----------+
What I'm trying to do is to do SUM(salary) from customers and subtract it with the SUM(amount) from orders table. I have tried with this query:
SELECT id ,NAME,SUM(salary),SUM(amount),SUM(salary)-SUM(amount)
FROM customers a LEFT JOIN orders b ON a.id=b.customer_id
GROUP BY NAME;
This will return the following result, which some of them return incorrect value:
+------+--------+-------------+-------------+-------------------------+
| id | name | SUM(salary) | SUM(amount) | SUM(salary)-SUM(amount) |
+------+--------+-------------+-------------+-------------------------+
| 5 | akil | 1000.00 | NULL | NULL |
| 2 | khilan | 1500.00 | 1300 | 200.00 |
| 3 | muffy | 17000.00 | 15300 | 1700.00 |
| 6 | rajesh | 5000.00 | NULL | NULL |
| 1 | ramesh | 2300.00 | 800 | 1500.00 |
| 4 | suresh | 24000.00 | 300 | 23700.00 |
+------+--------+-------------+-------------+-------------------------+
My expected output is as following:
+------+--------+-------------+-------------+-------------------------+
| id | name | SUM(salary) | SUM(amount) | SUM(salary)-SUM(amount) |
+------+--------+-------------+-------------+-------------------------+
| 5 | akil | 1000.00 | NULL | 1000 |
| 2 | khilan | 1500.00 | 1300 | 200.00 |
| 3 | muffy | 8500 | 15300 | -6800 |
| 6 | rajesh | 5000.00 | NULL | 5000 |
| 1 | ramesh | 2300.00 | 400 | 1900.00 |
| 4 | suresh | 24000.00 | 300 | 23700.00 |
+------+--------+-------------+-------------+-------------------------+
One way is to make calculation on orders into sub-query.
To cater for NULL value, you can use IFNULL(value,0).
SELECT id,NAME,SUM(salary),amt,SUM(salary)-IFNULL(amt,0)
FROM customers a LEFT JOIN
(SELECT customer_id, SUM(amount) amt FROM orders GROUP BY customer_id) b
ON a.id=b.customer_id
GROUP BY NAME;

Running total by item and week

I am trying to determine what my inventory level for each product is at the end of each business week.
I have a table that records all product transactions
+------------+-------------+------------+------------+
| ProductID | Quantity | Created_at |Cause |
+------------+-------------+------------+------------+
| 1 | 200 | 2015-06-01 |Delivery |
| 1 | -2 | 2015-06-02 |Order |
| 1 | -1 | 2015-06-12 |Order |
| 2 | 45 | 2015-06-15 |Delivery |
| 2 | -5 | 2015-06-16 |Order |
| 2 | -1 | 2015-06-17 |Broken |
| 1 | 100 | 2015-06-21 |Delivery |
+------------+-------------+------------+------------+
I would need to sum the quantity only up to the particular date, by product, to show something like this
+------------+-------------+------------+
| ProductID | Quantity | Week |
+------------+-------------+------------+
| 1 | 198 | 2015-06-05 |
| 1 | 197 | 2015-06-12 |
| 1 | 197 | 2015-06-19 |
| 2 | 39 | 2015-06-19 |
| 1 | 297 | 2015-06-26 |
| 2 | 39 | 2015-06-26 |
+------------+-------------+------------+
I have tried various combinations of With Rollup and #runtot:=
But have not been successful so far.
So, something like:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(product_id INT NOT NULL
,created_at DATE NOT NULL
,quantity INT NOT NULL
,cause VARCHAR(20) NOT NULL
,PRIMARY KEY(product_id,created_at)
);
INSERT INTO my_table VALUES
(1,'2015-06-01',200,'Delivery'),
(1,'2015-06-02', -2,'Order'),
(1,'2015-06-12', -1,'Order'),
(2,'2015-06-15', 45,'Delivery'),
(2,'2015-06-16', -5,'Order'),
(2,'2015-06-17', -1,'Broken'),
(1,'2015-06-21',100,'Delivery');
SELECT x.*
, CASE WHEN #prev = product_id THEN #i:=#i+total ELSE #i:=total END running
, #prev:=product_id prev
FROM
( SELECT product_id
, YEARWEEK(created_at) yw
, SUM(quantity) total
FROM my_table
GROUP
BY product_id
, yw
) x
, (SELECT #prev:=null,#i:=0) vars
ORDER
BY product_id
, yw;
+------------+--------+-------+---------+------+
| product_id | yw | total | running | prev |
+------------+--------+-------+---------+------+
| 1 | 201522 | 198 | 198 | 1 |
| 1 | 201523 | -1 | 197 | 1 |
| 1 | 201525 | 100 | 297 | 1 |
| 2 | 201524 | 39 | 39 | 2 |
+------------+--------+-------+---------+------+

SELECT the customer who has ordered the greatest quantity of Products?

I'm trying to make query to find the Customer who has ordered the greatest quantity of Products from the following table!
mysql> select * from ORDERS;
+---------+---------+------------+-----+
| CUSTNUM | PRODNUM | DATE | QTY |
+---------+---------+------------+-----+
| 125216 | 2323 | 2016-03-21 | 2 |
| 136101 | 2357 | 2016-03-21 | 5 |
| 136101 | 2357 | 2016-10-12 | 1 |
| 136101 | 2357 | 2016-11-25 | 5 |
| 136101 | 3737 | 2016-10-12 | 10 |
| 136101 | 9193 | 2016-11-25 | 5 |
| 182764 | 2357 | 2015-03-21 | 12 |
| 182764 | 2357 | 2016-05-12 | 10 |
| 212836 | 3737 | 2015-09-16 | 6 |
| 455566 | 4143 | 2016-02-09 | 10 |
| 455566 | 4143 | 2016-05-12 | 10 |
+---------+---------+------------+-----+
expected result
+-------------+------------------+
| CUSTNUM | quantity_ordered |
+-------------+------------------+
| 136101 | 26 |
+-------------+------------------+
Thanks in advance for help.
Use group by clause.
For more info,
Please refer some tutorials
Or read the official docs
SELECT CUSTNUM, SUM(QTY) s FROM ORDERS GROUP BY CUSTNUM
ORDER BY s DESC LIMIT 1
SQLfiddle

MySQL - Select to retrieve last datetime

I've got a table in MySQL:
| period_duration | duration | sample | corner | country | partner | ok_rate
+---------------------+----------+--------+----------+---------+-----------------------+-------------------------
| 2014-12-15 17:00:00 | 3600 | 1 | GRPS_INB | ARG | Charlie | 98 |
| 2014-12-15 17:00:00 | 3600 | 1 | GRPS_INB | DEU | Jack | 90 |
| 2014-12-15 17:00:00 | 3600 | 1 | GRPS_INB | NLD | Will | 100 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | ARG | Charlie | 98 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | DEU | Jack | 90 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | NLD | Will | 100 |
+-----------------+-------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------------------+-------+
| period_duration | datetime | NO | PRI | 0000-00-00 00:00:00 | |
| duration | varchar(6) | YES | | NULL | |
| sample | varchar(2) | YES | | NULL | |
| corner | varchar(10) | YES | | NULL | |
| country | varchar(60) | NO | PRI | | |
| partner | varchar(60) | NO | PRI | | |
| ok_rate | int(8) | YES | | NULL | |
+-----------------+-------------+------+-----+---------------------+-------+
This table increases from hour to hour.
I need a shellscript that will check each line from the last hour and that has an "ok_rate" lower than a given value, and return them to me on a select.
The select should bring country, the partner, and the ok_rate.
Example:
Let's say I want it to be done with <=98%¨on "ok_rate".
My returning rows would be:
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | ARG | Charlie | 98 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | DEU | Jack | 90 |
So far, I could only make it bring me the values below 98%, but not those that are also the last datetime that exists:
select country, partner, ok_rate from TABLE where ok_rate <= '98'
But how can I add a WHERE clause the makes it understand I want the last existing datetime that exists on period_duration too?
I mean something like:
SELECT country, partner, ok_rate FROM TABLE WHERE pdp_in_ok_rate <=98 AND (period_duration IS THE LAST ONE)?
This query should return what you want:
SELECT country, partner, ok_rate
FROM TABLE WHERE ok_rate <= 98
AND period_duration = (SELECT MAX(period_duration)
FROM TABLE)
Look in to GROUP BY for more detail because I'm not exactly sure what you want but something like this should help:
SELECT country, partner, ok_rate FROM TABLE
WHERE ok_rate <= '98'
GROUP BY `partner`, `country`
HAVING period_duration = MAX(period_duration);

Complex MySQL query summing joined records where parent and child ids are equal

Maybe this will be an easy one for some of you MySQL masters who see this stuff like a level 3 children's book.
I have multiple tables that I'm joining to produce statistical data for a report and I'm getting tripped up at the moment trying to figure it out. It's obviously imperative the figures are correct because it impacts a number of decisions going forward.
Here's the lay of the land (not the full picture, but you'll get the point):
Affiliate Table
+----+-----------+------------+---------------------+
| id | firstname | lastname | created_date |
+----+-----------+------------+---------------------+
| 1 | Mike | Johnson | 2010-11-22 17:44:37 |
| 2 | Trevor | Wilson | 2010-12-23 16:24:24 |
| 3 | Bob | Parker | 2011-11-04 10:33:49 |
+----+-----------+------------+---------------------+
Now our query should only find results for Bob Parker (id 3) so I'll only show example results for Bob.
Affiliate Link Table
+-----+-----------+--------------+-----------+----------+---------------------+
| id | parent_id | affiliate_id | link_type | linkhash | created_date |
+-----+-----------+--------------+-----------+----------+---------------------+
| 21 | NULL | 3 | PRODUCT | fa2e82a7 | 2011-06-15 16:18:37 |
| 27 | NULL | 3 | PRODUCT | 55de2ae7 | 2011-06-23 01:03:00 |
| 28 | NULL | 3 | PRODUCT | 02cae72f | 2011-06-23 01:03:00 |
| 29 | 27 | 3 | PRODUCT | a4dfb2c8 | 2011-06-23 01:03:00 |
| 30 | 28 | 3 | PRODUCT | 72cea1b2 | 2011-06-23 01:03:00 |
| 36 | 21 | 3 | PRODUCT | fa2e82a7 | 2011-06-23 01:07:03 |
| 59 | 21 | 3 | PRODUCT | ec33413f | 2011-11-04 17:49:17 |
| 60 | 27 | 3 | PRODUCT | f701188c | 2011-11-04 17:49:17 |
| 69 | 21 | 3 | PRODUCT | 6dfb89fd | 2011-11-04 17:49:17 |
+-----+-----------+--------------+-----------+----------+---------------------+
Affiliate Stats
+--------+--------------+--------------------+----------+---------------------+
| id | affiliate_id | link_id | order_id | type | created_date |
+--------+--------------+---------+----------+----------+---------------------+
| 86570 | 3 | 21 | NULL | CLICK | 2013-01-01 00:07:31 |
| 86574 | 3 | 21 | NULL | PAGEVIEW | 2013-01-01 00:08:53 |
| 86579 | 3 | 21 | 411 | SALE | 2013-01-01 00:09:52 |
| 86580 | 3 | 36 | NULL | CLICK | 2013-01-01 00:09:55 |
| 86582 | 3 | 36 | NULL | PAGEVIEW | 2013-01-01 00:09:56 |
| 86583 | 3 | 28 | NULL | CLICK | 2013-01-01 00:11:04 |
| 86584 | 3 | 28 | NULL | PAGEVIEW | 2013-01-01 00:11:04 |
| 86586 | 3 | 30 | NULL | CLICK | 2013-01-01 00:30:18 |
| 86587 | 3 | 30 | NULL | PAGEVIEW | 2013-01-01 00:30:20 |
| 86611 | 3 | 69 | NULL | CLICK | 2013-01-01 00:40:19 |
| 86613 | 3 | 69 | NULL | PAGEVIEW | 2013-01-01 00:40:19 |
| 86619 | 3 | 69 | 413 | SALE | 2013-01-01 00:42:12 |
| 86622 | 3 | 60 | NULL | CLICK | 2013-01-01 00:46:00 |
| 86624 | 3 | 60 | NULL | PAGEVIEW | 2013-01-01 00:46:01 |
| 86641 | 3 | 60 | NULL | PAGEVIEW | 2013-01-01 00:55:58 |
| 86642 | 3 | 30 | 415 | SALE | 2013-01-01 00:56:35 |
| 86643 | 3 | 28 | NULL | PAGEVIEW | 2013-01-01 00:56:43 |
| 86644 | 3 | 60 | 417 | SALE | 2013-01-01 00:56:52 |
+--------+--------------+---------+----------+----------+---------------------+
Orders
+------+--------------+---------+---------------------+
| id | affiliate_id | total | created_date |
+------+--------------+---------+---------------------+
| 411 | 3 | 138.62 | 2013-01-01 00:09:50 |
| 413 | 3 | 312.87 | 2013-01-01 00:09:52 |
| 415 | 3 | 242.59 | 2013-01-01 00:09:55 |
| 417 | 3 | 171.18 | 2013-01-01 00:09:55 |
+------+--------------+---------+---------------------+
Now the results that I need should look like this (only show main/parent link id)
+---------+---------+
| link_id | total |
+---------+---------+
| 21 | 451.49 | <- 1 order from parent (21), 1 from child (69)
| 27 | 171.18 | <- 1 order from child (69)
| 28 | 242.59 | <- 1 order from child (30)
+---------+---------+
I'm not quite sure how to write the query so that I can sum where affiliate_link.id and affiliate_link.parent_id are combined. Is this even possible with a couple of JOINs and GROUPing?
I'm not too sure why you have denormalised affiliate_id (by placing it in each table) and, therefore, whether one can rely on all Stats and Orders that stem from a particular Link to have the same affiliate_id as that Link.
If it's possible, I'd suggest changing the AffiliateLink.parent_id column such that parent records point to themselves (rather than NULL):
UPDATE AffiliateLink SET parent_id = id WHERE parent_id IS NULL
Then it's a simple case of joining and grouping:
SELECT AffiliateLink.parent_id AS link_id,
SUM(Orders.total) AS total
FROM AffiliateLink
JOIN AffiliateStats ON AffiliateStats.link_id = AffiliateLink.id
JOIN Orders ON Orders.id = AffiliateStats.order_id
WHERE AffiliateLink.affiliate_id = 3
GROUP BY AffiliateLink.parent_id
See it on sqlfiddle.
If it's not possible to make the change, you can effectively create the resulting AffiliateLink table using UNION (but beware the performance implications, as MySQL will not be able to use indexes on the result):
(
SELECT parent_id, id, affiliate_id FROM AffiliateLink WHERE parent_id IS NOT NULL
UNION ALL
SELECT id , id, affiliate_id FROM AffiliateLink WHERE parent_id IS NULL
) AS AffiliateLink
See it on sqlfiddle.