Query SUM mysql with if condition - mysql

I have some table in mysql database like this.
id | product | warehouse | price | date_shipping
------------------------------------------------
1 | Salt | 15 | 300 | 2017-03-08
2 | Salt | 15 | 300 | 2017-03-09
I want to SUM that column price with several condition. This is the condition.
From the product salt if the warehouse is have same id I don't want to SUM price value.
This is my second condition.
id | product | warehouse | price | date_shipping
------------------------------------------------
1 | Salt | 15 | 300 | 2017-03-08
2 | Salt | 18 | 300 | 2017-03-09
From the product salt if the warehouse is have different id I want to SUM price value.
This is the result what I want from the query.
From first condition :
salt | 15 | 300
From second condition :
salt | 15,18 | 600
This is query what I have doing.
SELECT product, GROUP_CONCAT(warehouse SEPARATOR ',') as warehouse, SUM(price)
FROM db_product
Somebody can help me with this ? Thank you.

Your problem requires two aggregations. The first one identifies, for each product in a warehouse, the record having the earliest shipping date. Then, a second aggregation is needed to group concatenate the warehouses for each product.
SELECT t.product,
GROUP_CONCAT(t.warehouse) AS warehouses,
SUM(t.price) AS total
FROM
(
SELECT t1.product,
t1.warehouse,
t1.price
FROM db_product t1
INNER JOIN
(
SELECT product, warehouse, MIN(date_shipping) AS min_date_shipping
FROM db_product
GROUP BY product, warehouse
) t2
ON t1.product = t2.product AND
t1.warehouse = t2.warehouse AND
t1.date_shipping = t2.min_date_shipping
) t
GROUP BY t.product
Output:
Demo here:
Rextester

Related

Find multiple totals by adding values from mysql table

I need to create a number adding all the values i can find in the db related to a specific customer.
Ex.
| Cust. | Value |
| 1 | 3 |
| 2 | 1 |
| 1 | 1 |
| 2 | 1 |
| 3 | 5 |
The result i want is : Customer #1 = 4, Customer #2 = 2; Customer #3 = 5.
There is a way to do that right into the mysql query?
Try Below query.
Select CONCAT('Customer #' , cust) as customer , sum(Value)
FROM customer_table
Group By cust
You want to SUM the values with a specific GROUP BY clause. Think of the GROUP BY as dividing rows into buckets and the SUM as aggregating the contents of those buckets into something useful.
Something like:
SELECT SUM(Value) FROM table GROUP BY Cust

Is this select subquery avoidable?

I have two tables (Invoices and taxes) in mysql:
Invoices:
- id
- account_id
- issued_at
- total
- gross_amount
- country
Taxes:
- id
- invoice_id
- tax_name
- tax_rate
- taxable_amount
- tax_amount
I'm trying to retrive a report like this
rep_month | country | total_amount | tax_name | tax_rate(%) | taxable_amount | tax_amount
--------------------------------------------------------------------------------------
2017-01-01 | ES | 1000 | TAX1 | 21 | 700 | 147
2017-01-01 | ES | 1000 | TAX2 | -15 | 700 | 105
2016-12-01 | FR | 100 | TAX4 | 20 | 30 | 6
2016-12-01 | FR | 100 | B2B | 0 | 70 | 0
2017-01-01 | GB | 2500 | TAX3 | 20 | 1000 | 200
The idea behind this is that an invoice has a has_many relation with taxes. So an invoice can have or not taxes. The report should show the total amount collected (total_amount) for a given country (regardess if it includes taxes)
and indicate which part of that total amount is taxable (taxable_amount) for an specific tax.
My current approach is this one:
SELECT
DATE_FORMAT(invoices.issued_at, '%Y-%m-01') AS rep_month,
invoices.country AS country
( SELECT sum(docs.gross_amount)
FROM invoices AS docs
WHERE docs.country = invoices.country
AND DATE_FORMAT(docs.issue_date, '%Y-%m-01') = rep_month
) AS total_amount,
taxes.tax_name AS tax_name,
taxes.tax_rate AS tax_rate,
SUM(taxes.taxable_amount) AS taxable_amount,
SUM(taxes.tax_amount) AS tax_amount
FROM invoices
JOIN taxes ON invoices.id = taxes.document_id
AND documents.issue_date BETWEEN '2016-01-01' AND '2017-12-31'
GROUP BY account_id, rep_month, country, tax_name, tax_rate
ORDER BY country desc
Well, this works but for a real dataset (thousands of records) it's really slow as the select subquery for retrieving the total_amount is being run for each row of the report.
I cannot make a LEFT JOIN taxes with a direct SUM(gross_amount) as the GROUP BY groups by tax name and rate and I need to show the total collected per country regardless if the amount was taxed or not. Is there a faster alternative to this?
I do not know the exact use case of using this query but the issue is the way with which you're trying to structure the DB, you're trying to get the entire data in one go.
Ideally, you should run the query you have and store in a different table (summary table) and then query directly from the summary table whenever you want. And if you have a new entry in the Invoices table then you can use the query to run either on every entry or periodically update the summary table via a cronjob.

Joining multiple select sql statements (4 tables)

I need to join together 2 SQL statements and both of those statements work on their own. But I don't know how to combine both into 1 SQL statement.
I have two tables in 1st statement, TR120 and TR1201.
The SQL is this:
select
PRODUCT, PRICE, QUANTITY, INVOICE.DATE
from
TR1201
left join
(select
DATE, ID as INVOICE_ID, INVOICE
from TR120) as INVOICE on INVOICE.INVOICE_ID = ID
where
INVOICE.DATE >= '2016-06-01' and INVOICE.DATE <= '2016-06-30'
This returns a list of all the products I sold, with price, quantity and date of sales in a specific time frame from 01-06-16 till 30-06-16.
Now I need to find out the latest price that I bought product for in different two tables TR100 and TR1001 based on the product and date of sale from the 1st SQL statement.
select
PRODUCT, PRICE, SUP.DATE
from
TR1001
left join
(select
DATE, ID as SUP_ID, SUP_INVOICE
from TR100) as SUP on SUP.SUP_ID = ID
This returns a list of all the products that I have bought with a price and a date. I only need last record from this query based on product and date of purchased.
TR120
ID | INVOICE | DATE
1 | 000001 |2016-06-05
2 | 000002 |2016-06-15
3 | 000003 |2016-06-25
TR1201
ID | PRODUCT | PRICE A | QUANTITY
1 | A | 2,00 | 5
2 | A | 2,00 | 2
3 | A | 2,00 | 1
TR100
ID | SUP_INVOICE | DATE
1 | 160001 | 2016-05-30
2 | 160002 | 2016-06-16
TR1001
ID | PRODUCT | PRICE B
1 | A | 0,5
2 | A | 0,7
The result I am trying to get is this:
PRODUCT | PRICE A (tr1201) | QUANTITY | DATE (tr100) | PRICE B (tr1001)
A | 2 | 5 | 2016-05-30 | 0,5
A | 2 | 2 | 2016-05-15 | 0,5
A | 2 | 1 | 2016-05-16 | 0,7
That is all I want to do :(
Have you tried first_value?
FIRST_VALUE ( [scalar_expression ] )
OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )
it works like this:
select distinct id,
first_value(price) over (partition by id (,sup) order by date DESC (latest, ASC for oldest)) as last_price
from table;
Documentation can be found here: https://msdn.microsoft.com/en-us/library/hh213018.aspx
I don't have your tables so cannot test and therefore am providing advice only.
I think what you need is an Outer apply like this instead of joins
select
T1.Product
, T1.Price
, T2.DATE -- Alias this
, T2.Price -- Alias this
, T3.DATE -- Alias this
, T3.Price -- Alias this
from T1
OUTER APPLY (
select top 1
Date
,Price
from table2
WHERE ID = T1.Id AND product = T1.Product-- plus any other joins
ORDER BY Date desc
) as T2
OUTER APPLY (
select top 1
Date
,Price
from table3
WHERE ID = T1.Id AND product = T1.Product-- plus any other joins
ORDER BY Date desc
) as T3

Group by a common coloumn in a number of tables which are listed in another table

I have a db with the following structure. each row in my institution table has a daily info saved in a separate table. what we want is how to query db such that we obtain the sum of price column of each institution info table grouped by corresponding days in _info tables. my db is MySQL.
Table institutions :
id | institution_name | institution_info_table_name
-----------------------------------------------------
1 | "A" | "A_info"
-----------------------------------------------------
2 | "B" | "B_info"
Table A_info :
id | date | price
-----------------------
1 | 2013/02/12 | 12
-----------------------
2 | 2013/02/13 | 20
Table B_info :
id | date | price
-----------------------
1 | 2013/02/12 | 30
-----------------------
2 | 2013/02/13 | 50
output :
date | price
------------------
2013/02/12 | 42
------------------
2013/02/13 | 70
Edit :
I tried following query but it did not work right :
"select sum( A_info.price) ,A_info.date from A_info,B_info group by date"
This is pretty simple , try as
select
x.date,
sum(x.price) as price
from
(
(
select
date,
sum(price) as price
from A_info
group by date
)
union all
(
select
date,
sum(price) as price
from B_info
group by date
)
)x
group by x.date
Did you try this basic query?
select A_info.price+B_info.price from A_info, B_info where A_info.id=B_info.id and
A_info.data=B_info.date;

MySQL nested query

I have 2 tables, one containing products, one purchases. I'm trying to find the average of the last 3 purchase prices for each product. So in the example below, for the product 'beans' I would want to return the average of the last 3 purchase prices before the product time 1230854663, i.e. average of customer C,D,E (239)
Products
+-------+------------+
| Name | time |
+-------+------------+
| beans | 1230854764 |
+-------+------------+
Purchases
+----------+------------+-------+
| Customer | time | price |
+----------+------------+-------+
| B | 1230854661 | 207 |
| C | 1230854662 | 444 |
| D | 1230854663 | 66 |
| E | 1230854764 | 88 |
| A | 1230854660 | 155 |
+----------+------------+-------+
I've come up with a nested select query which nearly gets me there i.e. it works if I hard code the time:
SELECT products.name,(SELECT avg(temp.price) FROM (select purchases.price from purchases WHERE purchases.time < 1230854764 order by purchases.time desc limit 3) temp) as av_price
from products products
But if the query references product.time rather than a hard coded time such as below I get an error that column products.time does not exist.
SELECT products.name,(SELECT avg(temp.price) FROM (select purchases.price from purchases WHERE purchases.time < products.time order by purchases.time desc limit 3) temp) as av_price from products products
I'm not sure if I'm making a simple mistake with nested queries or I'm going about this in totally the wrong way and should be using joins or some other construct, either way I'm stuck. Any help would be greatfully received.
The only problem in your query is you haven't mentioned products table in your inner query.
SELECT products.name,(SELECT avg(temp.price)
FROM (select purchases.price from purchases,products
WHERE purchases.time < products.time order by purchases.time desc limit 3) temp) as
av_price from products products