how to divide using mysql query - mysql

This is my query
SELECT currency_code, SUM(
CASE
WHEN TYPE = 'buy'
THEN to_amount
END ) AS BUY, SUM(
CASE
WHEN TYPE = 'sell'
THEN to_amount
END ) AS SELL, SUM(
CASE
WHEN TYPE = 'sell'
THEN rate
END ) AS SELL_RATE, SUM(
CASE
WHEN TYPE = 'buy'
THEN rate
END ) AS BUY_RATE
FROM tb_currency
LEFT JOIN tb_bill ON tb_currency.CURRENCY_ID = tb_bill.CURRENCY_ID
AND tb_bill.TYPE
IN (
'buy', 'sell'
)
The output is
Right now i want to divide the value in the BUY field with the value in the BUY_RATE field. I tried with several query before and got error message 'Unknown column type BUY'.
How to solve this?

You need to do a subselect, something like this
SELECT *, (BUY/BUY_RATE) AS DIV_VALUE FROM (
SELECT currency_code, SUM(
CASE
WHEN TYPE = 'buy'
THEN to_amount
END ) AS BUY, SUM(
CASE
WHEN TYPE = 'sell'
THEN to_amount
END ) AS SELL, SUM(
CASE
WHEN TYPE = 'sell'
THEN rate
END ) AS SELL_RATE, SUM(
CASE
WHEN TYPE = 'buy'
THEN rate
END ) AS BUY_RATE
FROM tb_currency
LEFT JOIN tb_bill ON tb_currency.CURRENCY_ID = tb_bill.CURRENCY_ID
AND tb_bill.TYPE
IN (
'buy', 'sell'
)
)

Related

What kind of query optimization can be done on this query?

I'm listing out orders data based on this query. This query basically pulls the recurring orders data from the table. I'm also using some dropdown and a input field to search / filter query results.
SELECT
orders.id,
parent_id,
(
SELECT
COUNT(*)
FROM
orders o
WHERE
o.parent_id = orders.id
) AS recurring_order_count,
shopify_order_type,
shopify_order_id,
shopify_order_customer_ID,
coupon_code AS coupon,
FORMAT(shopify_order_total_price, 2) AS shopify_order_total_price,
FORMAT(
shopify_order_subtotal_price,
2
) AS shopify_order_subtotal_price,
FORMAT(
shopify_order_total_line_items_price,
2
) AS shopify_order_total_line_items_price,
FORMAT(commission_amount, 2) AS commission_amount,
(
CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected'
END
) AS is_paid,
(
CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated'
END
) AS is_invoice_generated,
DATE_FORMAT(
shopify_order_created_at,
'%m-%d-%Y'
) AS shopify_order_created_at,
(
CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused'
END
) AS is_paused,
DATE_FORMAT(
shopify_recurring_date,
'%m-%d-%Y'
) AS shopify_recurring_date
FROM
`orders`
WHERE
coupon_code LIKE '%GERALD8314%' OR shopify_order_id LIKE '%GERALD8314%' OR(
CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected'
END
) LIKE '%GERALD8314%' OR(
CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated'
END
) LIKE '%GERALD8314%' OR DATE_FORMAT(
shopify_order_created_at,
'%m-%d-%Y'
) LIKE '%GERALD8314%' OR(
CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused'
END
) LIKE '%GERALD8314%' OR DATE_FORMAT(
shopify_recurring_date,
'%m-%d-%Y'
) LIKE '%GERALD8314%' AND DATE_FORMAT(
shopify_order_created_at,
'%Y-%m-%d'
) BETWEEN ? AND ?
GROUP BY
`id`
HAVING
parent_id = 0 AND shopify_order_type = 1
ORDER BY
`id`
DESC
LIMIT 10 OFFSET 0
Is this query optimized? Is this SELECT COUNT(*) FROM orders WHERE o.parent_id = orders.id AS recurring_order_count line most expensive in terms of query execution speed? Is there anything I should take care to improve the query speed here? Please advise.
OR and LIKE with leading wildcard are terrible for performance. Consider having a FULLTEXT index across the relevant columns. If it is practical, it will be immensely faster.
WHERE coupon_code LIKE '%GERALD8314%'
OR shopify_order_id LIKE '%GERALD8314%' OR( CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected' END ) LIKE '%GERALD8314%' OR( CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated' END ) LIKE '%GERALD8314%'
OR DATE_FORMAT( shopify_order_created_at, '%m-%d-%Y' ) LIKE '%GERALD8314%' OR( CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused' END ) LIKE '%GERALD8314%'
OR DATE_FORMAT( shopify_recurring_date, '%m-%d-%Y' ) LIKE '%GERALD8314%'
AND DATE_FORMAT( shopify_order_created_at, '%Y-%m-%d' ) BETWEEN ? AND ?
Also, there may be surprises in the results. Note that you have
a OR b OR c AND d
which is the same as
a OR b OR (c AND d)
I suspect you wanted
(a OR b OR c) AND d
I think the GROUP BY is unnecessary. And the HAVING clauses can be merged into the WHERE.
GROUP BY `id`
HAVING parent_id = 0
AND shopify_order_type = 1
ORDER BY `id` DESC
This has multiple issues:
DATE_FORMAT( shopify_order_created_at, '%Y-%m-%d' ) BETWEEN ? AND ?
BETWEEN is "inclusive". The way you have written the query, it will include the entire ending day. This may not be what you wanted.
Assuming the variable is a DATE or DATETIME, it can be simplified to
shopify_order_created_at BETWEEN ? AND ?
There may be more tips; fix these then come back for more.

Explain me ways to understand this complex query

Can anyone help me to understand this big sql query. How do I break it down in small chunks to understand it ?
select t.Instrument as Instrument ,ClearingId as ClearingId,
ISNULL( PrevQty ,0) AS PrevQty,SettlePrice,
ISNULL(TodayBuyQty,0) as TodayBuyQty,
ISNULL( TodaySellQty ,0) AS TodaySellQty,
ISNULL(PrevQty +TodayBuyQty-TodaySellQty,0) as NetQty,
TodayBuyPrice, TodaySellPrice,LTP,PnL,Token
from
(
select Instrument,w.ClearingId as ClearingId,
ISNULL( PrevQty ,0) AS PrevQty,ISNULL(TodayBuyQty,0) as TodayBuyQty,
ISNULL( TodaySellQty ,0) AS TodaySellQty,
TodayAvgBuyPrice as TodayBuyPrice,TodayAvgSellPrice as TodaySellPrice,
LTP,PnL,w.Token
from
(
select Symbol as Instrument, ClearingId,
ISNULL(TodayBuyQty,0) as TodayBuyQty,
TodayAvgBuyPrice,
ISNULL( -TodaySellQty ,0) AS TodaySellQty,
TodayAvgSellPrice, NULL as LTP ,NULL as PnL ,
w.Token as Token
from
(
select Token, sum(Qty) as NetPositionQty, ClearingId,
sum(CASE WHEN Qty < 0 THEN Qty ELSE 0 END) as TodaySellQty,
sum(CASE WHEN Qty > 0 THEN Qty ELSE 0 END) as TodayBuyQty,
sum(CASE WHEN Qty < 0 THEN Qty * Price ELSE 0 END)
/
NULLIF(sum(CASE WHEN Qty < 0 THEN Qty ELSE 0 END), 0) as TodayAvgSellPrice,
sum(CASE WHEN Qty > 0 THEN Qty * Price ELSE 0 END)
/
NULLIF(sum(CASE WHEN Qty > 0 THEN Qty ELSE 0 END), 0) as TodayAvgBuyPrice
from
(
select m.Token,
(CASE WHEN ClearingId = 'SATP' THEN 'STRAITS' ELSE CASE WHEN ClearingId = 'BATP' THEN 'BPI' ELSE 'UOB' END END ) as ClearingId ,
Price/CAST(Multiplier AS float ) as Price,Qty
from
(
select Token , Exchange as ClearingId ,
LastTradePrice as Price ,
CASE WHEN Side = 'S' THEN -LastTradeQuantity ELSE LastTradeQuantity END as Qty
from Strategy_Orders
where ExchangeStatus in (9,10) )m
JOIN TokenMap t ON ( m.Token = t.Token)
UNION ALL
select m.Token, (CASE WHEN ClearingId = 'SATP' THEN 'STRAITS' ELSE CASE WHEN ClearingId = 'BATP' THEN 'BPI' ELSE 'UOB' END END ) as ClearingId ,
Price/CAST(Multiplier AS float ) as Price,
Qty
from
(
select Token , Exchange as ClearingId ,
LastTradePrice as Price ,
CASE WHEN Side = 'S' THEN -LastTradeQuantity ELSE LastTradeQuantity END as Qty
from Manual_Orders
where ExchangeStatus in (9,10) )m
JOIN TokenMap t ON ( m.Token = t.Token)
UNION ALL
select Token , ClearingId , TodayBuyPrice ,
TodayBuyQty as Qty
from EOD_Holdings
where CurrentDate =
( select top 1 CurrentDAte from EOD_Holdings
order by CurrentDAte desc
)
UNION ALL
select Token , ClearingId , TodaySellPrice ,
TodaySellQty as Qty
from EOD_Holdings
where CurrentDate = (
select top 1 CurrentDAte from EOD_Holdings
order by CurrentDAte desc
)
) x
group by Token,ClearingId) w
JOIN(select Token, Symbol from TokenMAp ) h on w.Token = h.Token
) w
FULL OUTER JOIN(
select Token, PrevQty , ClearingId
from EOD_Holdings
where CurrentDate = ( select top 1 CurrentDAte from EOD_Holdings order by CurrentDAte desc
)
) h
on w.Token = h.Token and w.ClearingId = h.ClearingId
)t
JOIN (
select * from LatestSettlePrices
) sp
on t.Instrument = sp.Instrument
You can break the query into chunks by looking at each subquery ("select ..." ) separately and running them to see the results. You need to start with the innermost queries that do not have other select statements in the "from" or "where" clause.
Also note that this query does not seem to be a clear, neither an optimal solution.
You would want to avoid using full outer joins and union all statements for the best performance.

Multiple sum in SQL query

SELECT sum( plot_status = 'OPEN' ) AS OPEN
, sum( plot_status = 'SOLD' ) AS SOLD
FROM `tbl_plot`
GROUP BY `plot_status
This is giving
OPEN SOLD
7 0
0 8
How to make it
OPEN SOLD
7 8
Or is it possible?
just remove the GROUP BY clause and it will work.
SELECT sum( plot_status = 'OPEN' ) AS `OPEN` ,
sum( plot_status = 'SOLD' ) AS SOLD
FROM `tbl_plot`
If there is present plot_name or id then group by that not by plot_status:
SELECT sum( plot_status = 'OPEN' ) AS
OPEN , sum( plot_status = 'SOLD' ) AS SOLD
FROM `tbl_plot`
GROUP BY //`plot_name or plot_id
This will work for you for individual plot.
And if you don't want that then remove the group by clause.
select * from
(
select sum( plot_status = 'OPEN' FROM tbl_plot ) AS OPEN
select sum( plot_status = 'SOLD' FROM tbl_plot ) As Sold
)tbl

how to join after left join complex mysql queries

I have this query
SELECT
currency_code,
SUM(CASE WHEN TYPE = 'buy'THEN to_amount END ) AS BUY,
SUM(CASE WHEN TYPE = 'sell' THEN to_amount END ) AS SELL,
SUM(CASE WHEN TYPE = 'sell' THEN rate END ) AS SELL_RATE,
SUM(CASE WHEN TYPE = 'buy' THEN rate END ) AS BUY_RATE,
AVG(CASE WHEN TYPE = 'buy' THEN rate END ) AS AVG_BUY_RATE,
AVG(CASE WHEN TYPE = 'sell' THEN rate END ) AS AVG_SELL_RATE
FROM tb_currency
LEFT JOIN tb_bill
ON tb_currency.CURRENCY_ID = tb_bill.CURRENCY_ID
AND tb_bill.TYPE IN ('buy', 'sell')
AND date( DATE_TIME ) >= '2011-01-01'
AND date( DATE_TIME ) <= '2011-01-11'
GROUP BY currency_code
that will output this:
Right now i want to join this query with another table called tb_user
the tb_user have PK called user_id and the tb_bill that is use in the query above also have foreign key called user_id
tb_user
user_id (pk)| user_name | branch_id
tb_bill
bill_id (pk) | user_id (fk)|
Desired result should be the above picture plus one column branch_id.
If it doesnt have branch_id, return null.
I tried several times but still cant join it correctly. Hope you guys can help.
Thanks.
The three conditions in the join (the AND clauses) might be giving you trouble. Those three conditions are selection criteria, not join criteria.
Also, your use of CASE looks odd to me. I'm sure it works, but IF might be better suited for a one-condition function. In the below, if the fields are floating point rather than integer then replace the 0 with 0.0.
SELECT currency_code,
SUM(IF(TYPE = 'buy', to_amount, 0)) AS BUY,
SUM(IF(TYPE = 'sell', to_amount, 0)) AS SELL,
SUM(IF(TYPE = 'sell', rate, 0)) AS SELL_RATE,
SUM(IF(TYPE = 'buy', rate, 0)) AS BUY_RATE,
AVG(IF(TYPE = 'buy', rate, 0)) AS AVG_BUY_RATE,
AVG(IF(TYPE = 'sell', rate, 0)) AS AVG_SELL_RATE,
tb_user.whatever_field,
tb_user.whatever_other_field
FROM tb_currency
LEFT JOIN tb_bill ON tb_currency.CURRENCY_ID = tb_bill.CURRENCY_ID
LEFT JOIN tb_user ON tb_bill.user_id = tb_user.user_id
WHERE tb_bill.TYPE IN ('buy', 'sell')
AND date( DATE_TIME ) >= '2011-01-01'
AND date( DATE_TIME ) <= '2011-01-11'
GROUP BY currency_code, tb_user.user_id
Finally, all-cap field names look odd to my eye as well. Whatever works for you though.
add user_id to SELECT part
after
LEFT JOIN tb_bill ON tb_currency.CURRENCY_ID = tb_bill.CURRENCY_ID
place
LEFT JOIN tb_user ON tb_user.id = tb_bill.user_id
also you missing WHERE ( put instead first AND )
and
GROUP BY currency_code, user_id

Left join in complicated sql query

Hi guys i have this query
SELECT currency_code, SUM(
CASE
WHEN TYPE = 'cash_in'
THEN amount
END ) AS cash_in, SUM(
CASE
WHEN TYPE = 'cash_out'
THEN amount
END ) AS cash_out, SUM(
CASE
WHEN TYPE = 'cash_in'
THEN amount
ELSE - amount
END ) AS balance
FROM tb_cash_transaction
LEFT JOIN tb_currency ON tb_currency.CURRENCY_ID = tb_cash_transaction.CURRENCY_ID
WHERE TYPE IN (
'cash_in', 'cash_out'
)
GROUP BY currency_code
That will output this:
The problem is the query dont display another currency_code KRW which dont have data in tb_cash_transaction. Example in tb_currency
How to solve this?
Try this
SELECT currency_code, SUM(
CASE
WHEN TYPE = 'cash_in'
THEN amount
END ) AS cash_in, SUM(
CASE
WHEN TYPE = 'cash_out'
THEN amount
END ) AS cash_out, SUM(
CASE
WHEN TYPE = 'cash_in'
THEN amount
ELSE - amount
END ) AS balance
FROM tb_currency
LEFT JOIN tb_cash_transaction ON tb_currency.CURRENCY_ID = tb_cash_transaction.CURRENCY_ID AND tb_cash_transaction.TYPE IN (
'cash_in', 'cash_out'
)
GROUP BY currency_code