SQL statement with two sums and inner joins of three tables - mysql

I have three tables in my mysql database
Table1 -> stockinfo
stock_id | stock_code | balance
1 | stock_01 | 545
2 | stock_02 | 105
3 | stock_03 | 70
Table2 -> stock_in
stock_id | quantity | date_time
1 | 50 | 2013-11-23
1 | 250 | 2013-12-25
1 | 300 | 2013-12-28
2 | 100 | 2013-11-24
2 | 150 | 2013-12-25
3 | 30 | 2013-12-29
3 | 40 | 2013-12-31
Table3 -> stock_out
stock_id | quantity | date_time
1 | 20 | 2013-12-23
1 | 35 | 2013-12-25
2 | 70 | 2013-11-24
2 | 75 | 2013-12-25
The first table stockinfo contains the stock information such as stock_code and balance, balance means the remaining quantity left for a stock. stock_in table contains all the stock in of stock item with different dates and time. stock_out tables contains all the stock out of stock item with different dates and time. I want an output similar to the table below. Total stock in and total stock out at a given date range.
Output : (I want to show total in and total out for the month of december 2013 only.)
stock_code | total_in | total_out | balance
1 | 550 | 55 | 545
2 | 150 | 75 | 105
3 | 70 | 0 | 70
Here is my sql statement :
Select stock_code,
sum(case when stock_in.date_time >= '2013-12-01' and stock_in.date_time <= '2013-12-31' then stock_in.quantity else 0 end) as Total_In,
sum(case when stock_out.date_time >= '2013-12-01' and stock_out.date_time <= '2013-12-31' then stock_out.quantity else 0 end) as Total_Out, balance from stockinfo
left join stock_in on stockinfo.stock_id = stock_in.stock_id
left join stock_out on stockinfo.stock_id = stock_out.stock_id
group by stock_code
For the output, I am getting incorrect total for total_in and total_out. I'm not sure which part I had it wrong. If I only query the total_in and remove the total_out, it is working fine. Likewise, if i only query the total_out and remove the total_in part, it is also working. Please advice me which part I might have error in my SQL. Thanks.

Try this:
SELECT s.stock_id, s.stock_code, IFNULL(si.Total_In, 0) Total_In,
IFNULL(so.Total_Out, 0) Total_Out, s.balance
FROM stockinfo s
LEFT JOIN (SELECT si.stock_id, SUM(si.quantity) Total_In
FROM stock_in si
WHERE si.date_time BETWEEN '2013-12-01' AND '2013-12-31'
GROUP BY si.stock_id
) si ON s.stock_id = si.stock_id
LEFT JOIN (SELECT so.stock_id, SUM(so.quantity) Total_Out
FROM stock_out so
WHERE so.date_time BETWEEN '2013-12-01' AND '2013-12-31'
GROUP BY so.stock_id
) so ON s.stock_id = so.stock_id
GROUP BY s.stock_id

Related

How to show one column value into multiple column by distinct that column by type or id

I have a table named "Price".
In this table, three types of prices i-e cash, credit, check prices and these prices show in column sale_type_price.
I want to display these prices in 3 different columns i-e cash price, credit price and check price:
item_id | sale_type | price
01 | 3 | 10
02 | 3 | 11
01 | 6 | 20
01 | 7 | 30
02 | 6 | 22
02 | 7 | 22
This is my table and I want the result like this:
item_id | Cash Price | credit price| check price
01 | 10 | 20 | 30
02 | 11 | 22 | 22
Can anyone assist me with this, please?
use case when expression
select item_id,
max(case when sale_type=3 then price end) as CashPrice,
max(case when sale_type=6 then price end) as creditprice,
max(case when sale_type=7 then price end) as checkprice
from tablename
group by item_id
You can also use joins to achieve the result
SELECT a.item_id, a.price AS CashPrice, b.price AS CreditPrice, c.price AS CheckPrice FROM Price a
LEFT JOIN Price b ON a.item_id = b.item_id AND b.sale_type = 6
LEFT JOIN Price c ON a.item_id = c.item_id AND c.sale_type = 7
WHERE a.sale_type = 3

SQL LEFT JOIN with COUNT that returns NULL values

I have two tables: one that stores the product id and one which stores total sales per product_id and per sale_date
Table Products
product_id
----------
1
2
3
Table Sales
product_id | sale_date | total
-----------+------------+-------
1 | 2017-01-01 | 1
1 | 2017-02-01 | 1
1 | 2017-03-01 | 1
There is no sales total for product 2 and product 3.
I would like to query the sales table in order to get 0 in front of the months where there is no sale for any product id.
The result I would like to achieve is this:
product_id | month | total
-----------+------------+-------
1 | 2017-01 | 1
1 | 2017-02 | 1
1 | 2017-03 | 1
2 | 2017-01 | 0
2 | 2017-02 | 0
2 | 2017-03 | 0
3 | 2017-01 | 0
3 | 2017-02 | 0
3 | 2017-03 | 0
Right now what I do is this:
SELECT DATE_FORMAT(sale_date, "%m-%Y") as month,
Products.product_id,
COUNT(Sales.product_id) as total
FROM products Products
LEFT OUTER JOIN sales Sales
ON Sales.product_id = Products.product_id
GROUP BY Products.product_id, month
and what I get is:
product_id | month | total
-----------+------------+-------
1 | 2017-01 | 1
1 | 2017-02 | 1
1 | 2017-03 | 1
2 | NULL | 0
3 | NULL | 0
What should I modify to get a row for each month when there is no sale total for any product id? Thank you
Use a cross join to generate the rows, then left in to bring in the values:
select p.product_id, d.sales_date,
coalesce(s.total, 0) as total
from products p cross join
(select distinct sales_date from sales) d left join
sales s
on s.product_id = p.product_id and s.sales_date = d.sales_date
order by p.product_id, d.sales_date;
Note: This assumes that all the dates you want are in sales. I should point out that you can use another source for the dates, if you have one, or list them explicitly.
Could you give a try to this query:
select
distinct p.product_id,
DATE_FORMAT(sale_date, "%m-%Y") as month,
if(p.product_id <> s.product_id, 0,total) as total
from products p,
sales s
order by p.product_id

How to SUM column in MySQL left join

So i have table cont_selling
---------------------------------
cont_selling_id | date |
---------------------------------
1 | 2015-05-24 |
2 | 2015-06-06 |
---------------------------------
table 02 cont_sold
----------------------------------------------------
cont_sold_id | cont_selling_id | price |
---------------------------------------------------
1 | 1 | 10 |
2 | 1 | 10 |
3 | 1 | 30 |
4 | 2 | 20 |
5 | 2 | 10 |
--------------------------------------------------
and table 03 payment
----------------------------------------------
payment_id | cont_selling_id | paid |
-----------------------------------------------
1 | 1 | 10 |
2 | 2 | 10 |
3 | 1 | 20 |
4 | 1 | 10 |
5 | 2 | 10 |
-----------------------------------------------
now i need to SELECT table based on
now i want to merge all these three tables based on cont_selling table cont_selling_id column
and want to SUM cont_sold table price column and payment table paid column
this is what i want to do
expecting output
---------------------------------------------
cont_selling_id | price | paid |
---------------------------------------------
1 | 50 | 40 |
2 | 30 | 20 |
---------------------------------------------
so i tried like this in mysql query but it give wrong sum result
SELECT
SUM(Z.price) as total,
SUM(P.amount) as paid
FROM cont_selling S
LEFT JOIN cont_sold Z
ON S.cont_selling_id = Z.cont_selling_id
LEFT JOIN payment P
ON S.cont_selling_id = P.cont_selling_id
GROUP BY S.cont_selling_id
for this above query i m getting output like this
---------------------------------------------
cont_selling_id | price | paid |
---------------------------------------------
1 | 150 | 40 |
2 | 60 | 120 |
---------------------------------------------
Here how you can do it using the aggegare part into inner queries and then join
select
cs.cont_selling_id,
price,
paid
from cont_selling cs
left join(
select sum(price) as price , cont_selling_id from cont_sold
group by cont_selling_id
)x on x.cont_selling_id = cs.cont_selling_id,
left join(
select sum(paid) as paid , cont_selling_id from payment
group by cont_selling_id
)y
on y.cont_selling_id = cs.cont_selling_id;
You should make two different queries with SUM and then combine them to get the desired result:
SELECT T1.cont_selling_id,T1.price,T2.paid
FROM
(SELECT c.cont_selling_id,SUM(cs.price) as price
FROM cont_selling c LEFT JOIN
cont_sold cs ON c.cont_selling_id=cs.cont_selling_id
GROUP BY c.cont_selling_id) as T1 JOIN
(SELECT c.cont_selling_id,SUM(p.paid) as paid
FROM cont_selling c LEFT JOIN
payment p ON p.cont_selling_id=c.cont_selling_id
GROUP BY c.cont_selling_id) as T2 ON T1.cont_selling_id=T2.cont_selling_id
Result:
cont_selling_id price paid
----------------------------
1 50 40
2 30 20
Sample result in SQL Fiddle.
This untested query should work:
with a as(select cont_selling_id , sum(price) as totalprice from cont_sold group by cont_selling_id),
with a as(select cont_selling_id , sum(paid) as totalpaid from payment group by cont_selling_id),
select c.cont_selling_id , totalprice, totalpaid from cont_selling c left join a.count_selling_id = c.count_selling_id
left join b.count_selling_id = c.count_selling_id
You have to create temporary tables, because there is no dependency between your table for price and paid.

Sort sql results by Month with unix

here's what im trying to achive:
i have 2 sql tables:
transactions and payplans
bellow is the structures of 2 tables:
transactions
uid | plan | date | payid | status
------------------------------------
12 | 3 | 1388534400 | 334 | 1
699 | 4 | 1388214400 | 335 | 1
payplans:
plan | plan_price
-------------------
3 | 9.99
4 | 19.99
with this query:
SELECT SUM(plan_price)
FROM transations AS t
INNER JOIN payplans AS p
ON t.plan = p.plan
WHERE t.status = '1'
i was able to calculate total sum of all "plan_price" rows,
but i would like to have the price sum for every month starting jan 2013
for example:
jan-13 | 9.99
feb-13 | 29.99
etc.
For MySQL
SELECT date_format(FROM_UNIXTIME(t.date), '%b-%y') as mnth,
SUM(plan_price)
FROM transations AS t
INNER JOIN payplans AS p
ON t.plan = p.plan
WHERE t.status = '1'
GROUP BY mnth;
SQLFiddle
You converting unix_timestamp to date using FROM_UNIXTIME
formatting it into 'MON-YY' format with DATE_FORMAT
then grouping by month.

Mysql join query

I'm using two tables in the database. These tables look like this:
Table A:
id | date
----------------------
12001 | 2011-01-01
13567 | 2011-01-04
13567 | 2011-01-04
11546 | 2011-01-07
13567 | 2011-01-07
18000 | 2011-01-08
Table B:
user | date | amount
----------------------------------
15467 | 2011-01-04 | 140
14568 | 2011-01-04 | 120
14563 | 2011-01-05 | 140
12341 | 2011-01-07 | 140
18000 | 2011-01-08 | 120
I need a query that will join these the two tables.
The first query should result in a total number of users from table A group by date and the number of unique users from table A grouped by date. That query looks like:
SELECT COUNT(DISTINCT id) AS uniq, COUNT(*) AS total, format_date(date, '%Y-%m-%d') as date FROM A GROUP BY date
From the second table I need the sum of the amounts grouped by dates.
That query looks like:
SELECT SUM(amount) AS total_amount FROM B GROUP BY DATE_FORMAT( date, '%Y-%m-%d' )
What I want to do is to merge these two queries into one on column "date", and that as a result I get the following list:
date | unique | total | amount
-----------------------------------------------
2011-01-01 | 1 | 1 | 0
2011-01-04 | 1 | 2 | 260
2011-01-05 | 0 | 0 | 140
2011-01-07 | 2 | 2 | 140
2011-01-08 | 1 | 1 | 120
How can I do that using one query?
Thanks for all suggestions.
select date_format(a.date, '%Y-%m-%d') as date, a.uniq, a.total, ifnull(b.amount, 0) as amount
from (
select count(distinct id) as uniq, count(*) as total, date
from tablea
group by date
) a
left join (
select sum(amount) as amount, date
from tableb
group by date
) b on a.date = b.date
order by a.date
I assume that field date is a datetime type. It's better to format output fields in final result set (date field in this case).
Your queries are fine everything they need is a join.