How to combine two sql expressions into one? - mysql

I have the following issue:
It is necessary to write a query that will output 'item_id', 'price_in_byr'.
'price_in_byr' is calculated as the 'price' of the items table multiplied by the currency rate at the maximum date of the rate from the table rates.
See Schema
I apologize for my English, I'll try to explain by example:
Goods with item_id = 5 costs 20 euros, in the rates table the maximum date for the euro is January 12, at that date the exchange rate was 25. Total our 'price_in_byr' is 25 * 20 = 500
My solution with temp table:
CREATE TABLE tempRate SELECT currency, MAX(rate) AS maxRate FROM rates GROUP
BY currency;
SELECT items.item_id,(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM items
LEFT JOIN tempRate ON items.currency = tempRate.currency;
Tell me please, how can I do it in one query?

You can just use a subquery:
SELECT
items.item_id,(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM
items
LEFT JOIN
(
SELECT
currency, MAX(rate) AS maxRate
FROM
rates
GROUP BY
currency
) AS tempRate
ON items.currency = tempRate.currency;
In practice, you substitute "tempRate" by (definition of tempRate) AS tempRate.
You can see an example at dbfiddle here
If you actually want the * most_recent_rate*, you'd do something completely different; insert a subquery to compute it. This subquery looks for all rates of the given currency, sorts them by their exchange_ts (meaning timestamp) in descending order, and just picks to top 1:
SELECT
items.item_id,(ifnull(
(
SELECT
rate AS most_recent_rate
FROM
rates
WHERE
rates.currency = items.currency
ORDER BY
exchange_ts DESC
LIMIT 1
)
, 1) * items.price) AS price_in_byr
FROM
items ;
dbfiddle here

You can make your tempRate query into a subquery:
SELECT
items.item_id,
(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM
items
LEFT JOIN (
SELECT currency, MAX(rate) AS maxRate
FROM rates
GROUP BY currency
) as tempRate ON items.currency = tempRate.currency;

I am not sure if mysql supports this level of subquery but see if it works:
select I.item_id, I.price * CR.rt
from
items as I,
(
select r.currency cy, r.rate rt
from
rates as r, (select currency, max(date) max_date from rates group by currency) as R_MAXDATES
where
r.currency = R_MAXDATES.currency
and r.date = R_MAXDATES.max_date;
) As CR
where
I.currency = CR.cy

Related

How to query GHTorrent's (SQL-like language) for most common languages per country

Based on this question How to query GHTorrent's (SQL-like language) for country/city/users number/repositories number? and first query here https://ghtorrent.org/gcloud.html, I am trying to get an sql query to get the most common coding language per country and ideally per month/year from the GHtorrent bigquery database. I have tried to edit this answer code https://stackoverflow.com/a/65460166/10624798/, but fail to get the correct join. My ideal outcome would looks something like this
country
Year
Month
Language
Number of commits
total_bytes
US
2016
Jan
Python
10000
46789390
CH
2016
Jan
Java
20000
5679304
Basically, I am not very good at creating SQL queries.
I checked the two examples of the query that you passed, then I found the common value that was the project_id and I modified the second example to bring the project_id and the created_date of the commits. Then I decided as you mention to format the created_date to bring the year and the month and to add it as a filter.
Then I join the two examples in a CTE and I only SELECT the names of the columns that are needed.
Finally I used a ROW_NUMBER only to bring the maximum value of the processed bytes of every language by country/year/month.
WITH ltb as(
select pl3.lang, sum(pl3.size) as total_bytes, pl3.project_id
from (
select pl2.bytes as size, pl2.language as lang, pl2.project_id
from (
select pl.language as lang, max(pl.created_at) as latest, pl.project_id as project_id
from `ghtorrent-bq.ght.project_languages` pl
join `ghtorrent-bq.ght.projects` p on p.id = pl.project_id
where p.deleted is false
and p.forked_from is null
group by lang, project_id
) pl1 join `ghtorrent-bq.ght.project_languages` pl2 on pl1.project_id = pl2.project_id
and pl1.latest = pl2.created_at
and pl1.lang = pl2.language
) pl3
group by pl3.lang, pl3.project_id
order by total_bytes desc
), fprt as(
SELECT country_code, count(*) AS NoOfCommits, c.project_id,
FORMAT_TIMESTAMP("%m", c.created_at)
AS formattedmonth,FORMAT_TIMESTAMP("%b", c.created_at)
AS formattedmonthname, FORMAT_TIMESTAMP("%Y", c.created_at)
AS formattedyear,
FROM `ghtorrent-bq.ght.commits` AS c
JOIN `ghtorrent-bq.ght.users` AS u
ON c.Committer_Id = u.id
WHERE NOT u.fake and country_code is not null
GROUP BY country_code, c.project_id, formattedmonth, formattedyear, formattedmonthname
ORDER BY NoOfCommits DESC
), almst as(
SELECT country_code,formattedmonth, formattedmonthname, formattedyear, lang, NoOfCommits, total_bytes FROM fprt JOIN ltb
on ltb.project_id=fprt.project_id
where country_code is not null
)
SELECT country_code, formattedyear as year, formattedmonthname as month, lang, NoOfCommits, total_bytes
FROM
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY country_code, formattedyear, formattedmonth ORDER BY total_bytes DESC) rn
FROM almst
) t
WHERE rn = 1
ORDER BY formattedyear asc, formattedmonth asc
Output:

How to stop this repetition and group by date

After multiple attempts I'm unable to get my required result from this query.
SELECT
cc.date as credi_date,
cd.date as debit_date,
cd.month AS month,
ROUND(IFNULL(cc.credit_amount,0),2) AS credit,
ROUND(IFNULL(cd.debit_amount,0),2) AS debit
FROM
(SELECT
DATE(cc.credit_date) as date,
MONTHNAME(cc.credit_date) as month,
IFNULL(SUM(cc.credit_amount),0) AS credit_amount
FROM
cust_credit cc
WHERE YEAR(cc.credit_date) = YEAR(NOW())
GROUP BY DATE(cc.credit_date)) cc
INNER JOIN
(SELECT
DATE(cd.debit_date) as date,
MONTHNAME(cd.debit_date) as month,
IFNULL(SUM(cd.debit_amount),0) AS debit_amount
FROM
cust_debit cd
WHERE YEAR(cd.debit_date) = YEAR(NOW())
GROUP BY DATE(cd.debit_date)) cd ON cc.month=cd.month
The problem is that this query repeats the rows multiple times. I don't know what thing cause this repetition and how can fix this. The image of result is given below.
My required result is
My credit table is give below
My debit table is give below
Yon should use a UNION in the subquery and then GROUP BY in the SELECT:
SELECT my_date,
my_month,
SUM(credit),
SUM(debit)
FROM (
SELECT cc.credit_date as my_date,
MONTHNAME(cc.credit_date) as my_month,
ROUND(SUM(IFNULL(cc.credit_amount,0)),2) AS credit,
0 AS debit
FROM cust_credit cc
WHERE YEAR(cc.credit_date) = YEAR(NOW())
GROUP BY cc.credit_date,
MONTHNAME(cc.credit_date)
UNION
SELECT
cd.debit_date ,
MONTHNAME(cd.debit_date) ,
0 ,
ROUND(SUM(IFNULL(cd.debit_amount,0)),2)
FROM cust_debit cd
WHERE YEAR(cd.debit_date) = YEAR(NOW())
GROUP BY cd.debit_date,
MONTHNAME(cd.debit_date)
) as TT
GROUP BY my_date,my_month
This is the Fiddle
Basically, your result is cross join between two query and that's the reason your are getting cross product i.e. total number of rows from credit x total number of rows from debit.
Because, month for all rows in debit and credit tables are same (i.e. January). But, you have unique date in both table
So, making below change should give you expected output.
ON cc.month=cd.month
to
ON cc.date = cd.date

Max And Sum mysql

I've to get all the orders from one customer, then get the sum of the orders and then get the max order.
I can't use order by and limit.
I got the result but i can't get the make sum and max work properly
here is my current query:
SELECT SUM(Qty * UnitPrice) AS Total FROM `Details`
WHERE ONo IN (
SELECT Orders.Ono
FROM Orders, Customers
WHERE Customers.FName = 'Charles' AND Customers.LName = 'Xavier' AND Customers.CNo = Orders.CNo
GROUP BY Orders.ONo
)
GROUP BY ONo
Total
7.50
20.99
54.47
49.98
8.00
Please try:
SELECT MAX(Total) as MaxTotal FROM (<your query comes here>) AS T

How to multiply only one row in a query?

SELECT user_id, currency, SUM( price ) AS totalPrice, created
FROM accounts WHERE user_id IN ( SELECT users.id FROM users
WHERE country_id ='$con_id' )
AND created BETWEEN '2013-02-01' AND '2013-02-28' GROUP BY currency
This query give me result like
Curreny totalPrice
SEK 10
USD 10
I want to multiply only SEK from 7. I have only USD rate in the database, so i want to multiply it in the query with 7 to get SEK rate. How can I do that in this query?
Your question is a little bit confusing. If I understand your question correctly, you want to multiply the value of total value by 7 if the currency is equal to SEK.
SELECT user_id,
currency,
SUM(price) * IF(currency = 'SEK', 7, 1) totalPrice,
created
FROM accounts
WHERE user_id
IN
(
SELECT users.id
FROM users
WHERE country_id = '$con_id'
) AND
created BETWEEN '2013-02-01' AND '2013-02-28'
GROUP BY currency
I would store all conversion rates in a table. For SEK you store 7.0 als conversion rate and vor USD 1.0. Simply multiplie the totalPrice with the conversion rate (with sub query)
Here is an ugly way to implement it:
SELECT user_id, currency,
CASE WHEN currency = 'SEK' THEN SUM(price)*7
ELSE SUM(price) END totalPrice, created
FROM accounts
WHERE user_id
IN ( SELECT users.id FROM users
WHERE country_id = '$con_id')
AND created BETWEEN '2013-02-01' AND '2013-02-28'
GROUP BY currency

compare aggregates with row data

I have a table in MySql related to purchase of Inventory.
The table format is as below :
itemname (varchar)
vendor (varchar)
pdate (datetime)
qty (decimal)
rate (decimal)
total (decimal)
id (mediumint) (autoincrement)
A report is to be generated that must have the following columns
Item HighestRate HighestRateDate LowestRate LowestRateDate % difference
--
Item is the itemname
HighestRate and HighestRateDate are rates at maximum
LowestRate and Date are rates at minimum
%difference is a basic difference percentage between highestrate and lowestrate of a row
I have prepared the following query
SELECT itemname,rate,pdate from purchases
group by itemname
having rate = max(rate)
order by itemname
which does generate one half of the report.
However since it requires both the lowest and highest rate. This report is incomplete and printing two reports makes comparison difficult.
Any help would be appreciated.
Thankyou
Here goes. It's not pretty but it works.
select min.itemname,
min.rate,
min.pdate,
max.rate,
max.pdate,
(max.rate - min.rate)/max.rate as diff
from (SELECT p.itemname,
p.rate,
pdate
from purchases p,
(select itemname,
max(rate) as rate
from purchases
group by itemname) max_values
where p.itemname = max_values.itemname
and p.rate = max_values.rate
) max,
(SELECT p.itemname,
p.rate,
pdate
from purchases p,
(select itemname,
min(rate) as rate
from purchases
group by itemname) min_values
where p.itemname = min_values.itemname
and p.rate = min_values.rate
) min
where max.itemname = min.itemname;
You'll need an index on (itemname, rate) for this query not to be awfully slow.
If there are two or more dates with same maximum (or minimum) rate, then a (more or less) random date will be selected. If you want to control that, change the ORDER BY rate ASC (to ORDER BY rate ASC, pdate DESC for example):
SELECT
di.itemname AS Item
, maxr.rate AS HighestRate
, maxr.pdate AS HighestRateDate
, minr.rate AS LowestRate
, minr.pdate AS LowestRateDate
, (maxr.rate - minr.rate)/maxr.rate --- calculations
AS PrecentDifference
FROM
( SELECT DISTINCT itemname
FROM purchases
) AS di
JOIN
purchases AS minr
ON minr.id = --- I guess this is the PK
( SELECT id
FROM purchases p
WHERE p.itemname = di.itemname
ORDER BY rate ASC
LIMIT 1
)
JOIN
purchases AS maxr
ON maxr.id =
( SELECT id
FROM purchases p
WHERE p.itemname = di.itemname
ORDER BY rate DESC
LIMIT 1
)