Left join in complicated sql query - mysql

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

Related

Total the aggregate in Select Case Statement

Is there a way to get a total from the aggregate in each select case statement? The following gives me the correct total by listing the total for each month in a column but I would like to have a single total for each case statement.
SELECT SUM(
CASE WHEN dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2016-12-31' THEN dbo.bill_t_ARTransaction.Amount ELSE 0 END
) AS 'Dec16'
, SUM(
CASE WHEN dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31' THEN dbo.bill_t_ARTransaction.Amount ELSE 0 END
) AS 'JAN17'
FROM dbo.bill_t_ARTransaction
INNER JOIN dbo.bill_t_TripTicket ON (
dbo.bill_t_ARTransaction.RunNumber = dbo.bill_t_TripTicket.RunNumber
)
INNER JOIN dbo.med_m_Company ON (
dbo.bill_t_TripTicket.CompanyCode = dbo.med_m_Company.CompanyCode
)
WHERE dbo.bill_t_TripTicket.CompanyCode = '105'
AND dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
GROUP BY dbo.bill_t_ARTransaction.TransactionDate
I just formated your SQL - so it will be more readable for human beings - and put it in a Subselect.
In the outer Select i just added the SUM of the two calculated columns
SELECT sums.*
,SUM(sums.DEC16 + sums.JAN17) AS TOTAL_SUM
FROM (
SELECT SUM( CASE WHEN dbo.bill_t_ARTransaction.TransactionDate
BETWEEN '2000-01-01'
AND '2016-12-31'
THEN dbo.bill_t_ARTransaction.Amount
ELSE 0
END
) AS DEC16
,SUM( CASE WHEN dbo.bill_t_ARTransaction.TransactionDate
BETWEEN '2000-01-01'
AND '2017-01-31'
THEN dbo.bill_t_ARTransaction.Amount
ELSE 0
END
) AS JAN17
FROM dbo.bill_t_ARTransaction
INNER JOIN dbo.bill_t_TripTicket
ON dbo.bill_t_ARTransaction.RunNumber = dbo.bill_t_TripTicket.RunNumber
INNER JOIN dbo.med_m_Company
ON dbo.bill_t_TripTicket.CompanyCode = dbo.med_m_Company.CompanyCode
WHERE dbo.bill_t_TripTicket.CompanyCode = '105'
AND dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
GROUP BY dbo.bill_t_ARTransaction.TransactionDate
) sums
I think you just want to get right of the GROUP BY:
SELECT SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2016-12-31'
THEN ba.Amount ELSE 0
END) AS Dec16,
SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
THEN ba.Amount ELSE 0
END) AS JAN17
FROM dbo.bill_t_ARTransaction ba INNER JOIN
dbo.bill_t_TripTicket bt
ON ba.RunNumber = bt.RunNumber INNER JOIN
dbo.med_m_Company c
ON bt.CompanyCode = c.CompanyCode
WHERE bt.CompanyCode = '105' AND
ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31';
Note the other changes I made to the query:
I removed the single quotes from the column aliases. Single quotes should only be used for string and date values (using them for column aliases is allowed but can cause confusion).
The tables are given aliases.
The column names are qualified with the aliases (the query is easier to write and to read.
Note that '105' should not have quotes, if CompanyCode is numeric.
I think the query can be simplified to:
SELECT SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2016-12-31'
THEN ba.Amount ELSE 0
END) AS Dec16,
SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
THEN ba.Amount ELSE 0
END) AS JAN17
FROM dbo.bill_t_ARTransaction ba INNER JOIN
dbo.bill_t_TripTicket bt
ON ba.RunNumber = bt.RunNumber
WHERE bt.CompanyCode = 105 AND
ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31';
The Company table does not appear to be being used.
You can do this:
SELECT DATENAME(MONTH, Transaction.TransactionDate) + RIGHT(YEAR(Transaction.TransactionDate), 2) AS MonthYear
, SUM(Transaction.Amount) AS Amount
FROM dbo.bill_t_ARTransaction Transaction
INNER JOIN dbo.bill_t_TripTicket Ticket
ON Transaction.RunNumber = Ticket.RunNumber
INNER JOIN dbo.med_m_Company Company
ON Ticket.CompanyCode = Company.CompanyCode
WHERE Ticket.CompanyCode = '105'
AND Transaction.TransactionDate >= '2000-01-01'
AND Transaction.TransactionDate < '2017-02-01'
GROUP BY DATENAME(MONTH, Transaction.TransactionDate) + RIGHT(YEAR(Transaction.TransactionDate), 2)
Assuming dbo.bill_t_ARTransaction.TransactionDate is a datetime(2): Are you aware that in 'DEC16' you are missing transaction from (as an example) 2016-12-31 11:00:00? BETWEEN is inclusive on both sides, and dates are defaulted to midnight (00:00:00) if no time component is defined. I altered the WHERE clause accordingly. I also added aliases to help the readability.

MySQL How to make a SELECT SUM from Table and multiplication from other SEARCH?

I have this query
SELECT ps_ur AS UR, COUNT(ps_ur) AS Value
FROM patient_services
GROUP BY UR
UNION ALL
SELECT eng_ur AS UR, COUNT(eng_ur) AS Value
FROM engagements
WHERE LENGTH( eng_ur )>0
GROUP BY UR
Result:
UR Value
002035 3
002400 2
005441 4
...
Now I need to calculate from Patient table Male/Female and multiply by the Value
Like this but right
SELECT
SUM( CASE WHEN patient_gender = 'Male' THEN 1 ELSE 0 END ) Male,
SUM( CASE WHEN patient_gender = 'Female' THEN 1 ELSE 0 END ) Female
FROM patients WHERE patient_ur
How to do this?
In that case you want wrap the first as inner query. Something like below. Now you can access the Value field saying xxx.Value and multiply or do whatever processing needed. Not sure where you want to multiply and thus couldn't reflect it in suggested query. Probably that's left as homework for you.
SELECT
SUM( CASE WHEN patient_gender = 'Male' THEN 1 ELSE 0 END ) Male,
SUM( CASE WHEN patient_gender = 'Female' THEN 1 ELSE 0 END ) Female
FROM patients JOIN (
SELECT ps_ur AS UR, COUNT(ps_ur) AS `Value`
FROM patient_services
GROUP BY UR
UNION ALL
SELECT eng_ur AS UR, COUNT(eng_ur) AS `Value`
FROM engagements
WHERE LENGTH( eng_ur )>0
GROUP BY UR ) xxx ON patients.patient_ur = xxx.UR

CASE Statement in SQL WHERE clause

I'm trying to fetch data from table where I'm using a CASE condition in the WHERE clause and currently I'm using following query:-
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)
AND CASE WHEN (
STATUS = 'Sold'
)
THEN delivery_date >= '2012-08-01'
END
But it returns 0 for total and NULL for purchase.
From your comment.
I want to use Case Statement, could u pls clarify me about case statament in where clause
You can use CASE statement in WHERE like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND ( STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref')
AND CASE STATUS
WHEN 'Sold'
THEN delivery_date >= '2012-08-01'
ELSE 1=1
END
Here you need to use ELSE 1=1. otherwise you will not get desired result. For more explanation see this SQLFiddle
I don't think that CASE can work that way. What you want is a slightly more complex expression as your WHERE clause. Probably something like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
(STATUS = 'Sold' AND delivery_date >= '2012-08-01')
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)

how to divide using mysql query

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'
)
)

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