MySQL stuck on this query - mysql

Is there is something wrong with this query?
It was tested and working (quite fast) and one day just stopped - never ends (query is wrong or something with MySQL?).
I have to update table turnover taking values from sales_history. Because key is vat_no, I have to join table clients to read customer vat_no from that table.
TURNOVER tbl
vat_no
billing_month
turnover
SALES_HISTORY tbl
customer_number
sales_amount
...
CLIENTS tbl
customer_number
vat_no
...
UPDATE turnover t
INNER JOIN (
SELECT c.vat_no, sales_history.billing_month, sales_history.customer_number, sum(sales_amount) as turnover
FROM sales_history
LEFT JOIN clients c
ON sales_history.customer_number = c.customer_number
WHERE sales_history.billing_month = '2018-01-01'
GROUP BY c.vat_no
) sales_history
ON sales_history.vat_no = t.vat_no
SET t.turnover = turnover
WHERE t.billing_month = '2018-01-01'

Why left join in the subquery if you need the result as key for update ?
i think you sould use INNER JOIN
UPDATE turnover t
INNER JOIN (
SELECT c.vat_no, sum(sales_amount) as turnover
FROM sales_history
INNER JOIN clients c ON sales_history.customer_number = c.customer_number
WHERE sales_history.billing_month = '2018-01-01'
and c.vat_no is not null
GROUP BY c.vat_no
) s ON s.vat_no = t.vat_no
SET t.turnover = turnover
WHERE t.billing_month = '2018-01-01'
and for performance be sure you have a composite index on
table turnover columns (billing_month , vat_no)
and on
table clients on column customer_number

Related

SQL UPDATE TABLE from SELECT query from other tables

I have bd hf3 and 5 tables there:
active_preset with columns (id , preset_id)
preset with columns (id , birja_id, trend_id, fractal, interval_up)
birja with columns (id , name)
trend with columns (id , name)
uq_active_preset with columns (id , birja, trend, fractal, interval_up)
In table preset I have a few records. Some of them are in table active_preset by foreign key preset_id. In table active_preset a few records exist once , a few more than once.
I need to update table uq_active_preset with records from table active_preset disregarding repetitions of records if they are present.
I did query from active_preset and it works good:
SELECT
b.name AS birja, p.fractal AS fractal , tre.name AS trend, p.interval_up AS interval_up
FROM hf3.active_preset AS ap
INNER JOIN hf3.preset AS p on p.id = ap.preset_id
INNER JOIN hf3.birja AS b on b.id = p.birja_id
INNER JOIN hf3.trend AS tre on tre.id = p.trend_id
GROUP BY b.name, p.fractal, tre.name, p.interval_up
HAVING COUNT(*) >= 1
But I don't know how to update uq_active_preset
I tried this and it returns syntax error:1064 :
UPDATE hf3.uq_active_preset uap SET
uap.birja = st.birja ,
uap.fractal = st.fractal,
uap.trend = st.trend,
uap.interval_up = st.interval_up,
FROM (SELECT b.name AS birja, p.fractal AS fractal , tre.name AS trend, p.interval_up AS interval_up
from hf3.active_preset AS ap
INNER JOIN hf3.preset AS p on p.id = ap.preset_id
INNER JOIN hf3.birja AS b on b.id = p.birja_id
INNER JOIN hf3.trend AS tre on tre.id = p.trend_id
GROUP BY b.name, p.fractal, tre.name, p.interval_up
HAVING COUNT(*) >= 1
) st
when you make an update using from is like you join the updated table with your query result. So, you need also a where statement in order to tell where those two are connected. Also, don't use alias of your updated table on set statement.
You need something like that:
UPDATE hf3.uq_active_preset uap SET birja=st.birja,fractal=st.fractal,trend=st.trend,interval_up=st.interval_up
FROM (SELECT b.name AS birja, p.fractal AS fractal , tre.name AS trend, p.interval_up AS interval_up
from hf3.active_preset AS ap
INNER JOIN hf3.preset AS p on p.id = ap.preset_id
INNER JOIN hf3.birja AS b on b.id = p.birja_id
INNER JOIN hf3.trend AS tre on tre.id = p.trend_id
GROUP BY b.name, p.fractal, tre.name, p.interval_up
HAVING COUNT(*) >= 1
) st
where uap.fkey=st.fkey

Mysql Select query with double JOIN statement

Hy guys. I need to select the customer_id who is on 'base' table, where the created date is the current date and where this customer dont have a budget_item executed on the current date. My query brings up an incorrect result. It show the customer_id of all budget_id that are not on that date..
What is wrong in my stetement?
PS.: I cannot consolidate the tables.
SELECT base.customer_id
FROM base
LEFT JOIN budget ON base.customer_id = budget.customer_id
LEFT JOIN budget_item ON budget.budget_id = budget_item.budget_id
WHERE
CAST(base.created as Date) = CURDATE()
AND budget_item.execution_date <> CURDATE();
Left join budget/budget_item specifically looking for items with the current date and then exclude them in WHERE by checking that some non-nullable column of budget_item is NULL (indicating no record was joined):
SELECT base.customer_id
FROM base
LEFT JOIN budget ON base.customer_id = budget.customer_id
LEFT JOIN budget_item ON budget.budget_id = budget_item.budget_id AND budget_item.execution_date = CURDATE()
WHERE
CAST(base.created as Date) = CURDATE()
AND budget_item.budget_id IS NULL;
Some prefer using NOT EXISTS for this, but the result and efficiency should be the same:
SELECT base.customer_id
FROM base
WHERE
CAST(base.created as Date) = CURDATE()
AND NOT EXISTS (
SELECT 1
FROM budget
JOIN budget_item ON budget.budget_id = budget_item.budget_id AND budget_item.execution_date = CURDATE()
WHERE budget.customer_id = base.customer_id
);
fiddle
Use aggregation:
SELECT base.customer_id
FROM base LEFT JOIN
budget bu
ON base.customer_id = bu.customer_id LEFT JOIN
budget_item bi
ON bu.budget_id = bi.budget_id
WHERE CAST(base.created as Date) = CURDATE()
GROUP BY base.customer_id
HAVING SUM(bi.execution_date = CURDATE()) = 0;

Return single record from another table with multiple records per transactionDate

How can I create a query that will return the latest Soa LoanableAmount based on the LoanApplicationDate.
Ex:
For LoanID = 1, I want to get the Soa record with SoaID = 2 since this is the latest loanable amount for this LoanApplicationDate - 2017-07-01.
So far this is what I have accomplished:
select *
from Loan L
join Soa S
ON S.EmployeeID = L.EmployeeID
where S.TransactionDate <= L.LoanApplicationDate
To illustrate what I want to accomplish, please see screenshot below.
https://www.db-fiddle.com/f/3PBossUJLYQTQZJfZymiph/0
I think you want a join and then to filter to get the most recent date:
select l.*, s.*
from Loan l join
Soa s
on s.employeeid = l.employeeid
where s.TransactionDate <= (select max(s2.TransactionDate)
from Soa s2
where s2.employeeid = l.employeeid and
s2.TransactionDate <= l.LoanApplicationDate
);
I think you need to set the condition on the join:
select
L.LoanID,
L.EmployeeID,
L.LoanAmount,
L.LoanApplicationDate,
S.LoanableAmount,
S.TransactionDate
from Loan L join Soa S
ON S.EmployeeID = L.EmployeeID and
S.TransactionDate = (select max(TransactionDate) from Soa where TransactionDate <= L.LoanApplicationDate)
See the demo
SQL DEMO
select *
from Loan L
join Soa S
ON S.EmployeeID = L.EmployeeID
and S.TransactionDate =
(select max(S2.TransactionDate)
from Soa S2
where S2.TransactionDate <= L.LoanApplicationDate
and S2.`EmployeeID` = L.`EmployeeID`
)
The below query will give you all employee ids with loanable amount withdrawn on latest date
Select employee_id,
LoanableAmount
transactionDate from table
having
transactionDate=max(transactionDate)
group by employee_id
You need to run a subquery for each row:
select q.*, S.LoanableAmount, S.TransactionDate from
(select
L.*
,(select SoaID from Soa x where x.EmployeeID = L.EmployeeID and x.TransactionDate <= L.LoanApplicationDate order by TransactionDate DESC limit 1) as SoaID
from Loan L) q
join Soa S on S.SoaID = q.SoaID
Line 4 will give you the SoaID of the row in the Soa table that has the newest date that is less than or equal to the Application Date, then with that ID you just join and show the rest of the fields.

Mysql Select unique record based on multiple columns and display only group and sum amount

Hi I am trying to query a table that conatains multiple duplicates on Code,Amount and Status How will I do this if I only one to get a result group according to the client_group name and get the sum of amount under that group
SELECT `client`.`client_group`
, FORMAT(SUM(`Data_result`.`Data_result_amount` ),2) as sum
FROM
`qwer`.`Data_result`
INNER JOIN `qwer`.`Data`
ON (`Data_result`.`Data_result_lead` = `Data`.`Data_id`)
INNER JOIN `qwer`.`Data_status`
ON (`Data_result`.`Data_result_status_id` = `Data_status`.`Data_status_id`)
INNER JOIN `qwer`.`client`
ON (`Data`.`Data_client_id` = `client`.`client_id`)
WHERE `Data_status`.`Data_status_name` IN ('PAID') AND MONTH(`Data_result`.`result_ts`) = MONTH(CURRENT_DATE())
AND YEAR(`Data_result`.`result_ts`) = YEAR(CURRENT_DATE())
GROUP BY `client`.`client_group`
Result of said query:
Table
Try to distinct before run the 'sum' check whether this solve your problem
SELECT `client_group` , FORMAT(SUM(`Data_result_amount` ),2) as sum from (
SELECT DISTINCT `client`.`client_group` , `Data_result`.`Data_result_amount`
FROM
`qwer`.`Data_result`
INNER JOIN `qwer`.`Data`
ON (`Data_result`.`Data_result_lead` = `Data`.`Data_id`)
INNER JOIN `qwer`.`Data_status`
ON (`Data_result`.`Data_result_status_id` = `Data_status`.`Data_status_id`)
INNER JOIN `qwer`.`client`
ON (`Data`.`Data_client_id` = `client`.`client_id`)
WHERE `Data_status`.`Data_status_name` IN ('PAID') AND MONTH(`Data_result`.`result_ts`) = MONTH(CURRENT_DATE())
AND YEAR(`Data_result`.`result_ts`) = YEAR(CURRENT_DATE())
) T
GROUP BY `client_group`
you can check the query here http://sqlfiddle.com/#!9/36a3f8/6

MySQL getting sum of tables with the same id

I have four tables person,loan,ca,payments
I would like to get the sum of all payments amounts and cash advance amounts which has the same ID as the loan joined with a person from a specific date.
Here is my code, but the sum is calculated incorrectly:
SELECT pd.*,
l.total_loan_amount,
sum(c.ca_total_amount) AS ctot,
sum(p.payment_amount)
FROM personal_data pd
LEFT JOIN loans l
ON pd.id_personal_data = l.id_personal_data
LEFT JOIN ca c
ON l.id_loan = c.id_loan
LEFT JOIN payments p
ON l.id_loan = p.id_loan
WHERE l.loan_date = curDate()
AND (
c.ca_date = curDate()
OR c.ca_date IS NULL
)
AND (
p.payment_date = curDate()
OR p.payment_date IS NULL
)
GROUP BY pd.id_personal_data
Doing that may sometimes retrieve invalid results because id may or may not sometimes be present on other table.
Try using a subquery for each column you want to retrieve.
SELECT pd.*,
l.total_loan_amount,
c.totalCA,
p.totalPayment
FROM personal_data pd
LEFT JOIN loans l
ON pd.id_personal_data = l.id_personal_data
LEFT JOIN
(
SELECT id_loan, SUM(ca_total_amount) totalCA
FROM ca
-- WHERE DATE(ca_date) = DATE(CURDATE()) OR
-- ca_date IS NULL
GROUP BY id_loan
) c ON l.id_loan = c.id_loan
LEFT JOIN
(
SELECT id_loan, SUM(payment_amount) totalPayment
FROM payments
-- WHERE DATE(payment_date) = DATE(CURDATE()) OR
-- payment_date IS NULL
GROUP BY id_loan
) p ON l.id_loan = p.id_loan
WHERE DATE(l.loan_date) = DATE(curDate())
I think dates on every payment and cash advance are irrelevant because you are looking for its totals based on the date of loan