avoid duplicate data when multiple left join - mysql

This is my sql select statement http://www.sqlfiddle.com/#!9/353e82/1,
This is the output
I use left join but the data will duplicate on output.
What I want is the data wont duplicate and only show once
Earnings
Total OT Pay - amount
Transport - amount
Uniform - amount
Deduction
Loan - amount
Unpaid Leave - amount
Thanks

If you want single row based on payslip_no then use below query-
SELECT
hrms_salary_payment.`payslip_no` AS payslip_no,
hrms_salary_payment.`payment_month` AS payment_month,
hrms_salary_payment.`basic_salary` AS basic_salary,
hrms_salary_payment.`hours_worken_week` AS hours_worken_week,
hrms_salary_payment.`ot_hours_worked` AS ot_hours_worked,
hrms_salary_payment.`total_ot_pay` AS total_ot_pay,
hrms_salary_payment.`employee_cpf` AS employee_cpf,
hrms_salary_payment.`employer_cpf` AS employer_cpf,
hrms_salary_payment.`sdl_payable` AS sdl_payable,
hrms_salary_payment.`net_salary` AS net_salary,
hrms_salary_payment.`payment_amount` AS payment_amount,
hrms_salary_payment.`payment_date` AS payment_date,
hrms_salary_additional.`item_remark` AS income,
hrms_salary_additional.`item_amount` AS income_amount,
hrms_salary_additional.`isCPF` AS isCPF,
hrms_salary_deduction.`deduction_remark` AS deduction_remark,
hrms_salary_deduction.`deduction_amount` AS deduction_amount
FROM `hrms_salary_payment`
LEFT JOIN `hrms_salary_additional` ON hrms_salary_additional.payment_id = hrms_salary_payment.payment_id
LEFT JOIN `hrms_salary_deduction` ON hrms_salary_deduction.payment_id = hrms_salary_payment.payment_id
where hrms_salary_payment.`payment_id` = 27
GROUP BY hrms_salary_payment.`payslip_no`;
But if you want 3 rows further distinquished by item_remarks then use below query-
SELECT
hrms_salary_payment.`payslip_no` AS payslip_no,
hrms_salary_payment.`payment_month` AS payment_month,
hrms_salary_payment.`basic_salary` AS basic_salary,
hrms_salary_payment.`hours_worken_week` AS hours_worken_week,
hrms_salary_payment.`ot_hours_worked` AS ot_hours_worked,
hrms_salary_payment.`total_ot_pay` AS total_ot_pay,
hrms_salary_payment.`employee_cpf` AS employee_cpf,
hrms_salary_payment.`employer_cpf` AS employer_cpf,
hrms_salary_payment.`sdl_payable` AS sdl_payable,
hrms_salary_payment.`net_salary` AS net_salary,
hrms_salary_payment.`payment_amount` AS payment_amount,
hrms_salary_payment.`payment_date` AS payment_date,
hrms_salary_additional.`item_remark` AS income,
hrms_salary_additional.`item_amount` AS income_amount,
hrms_salary_additional.`isCPF` AS isCPF,
hrms_salary_deduction.`deduction_remark` AS deduction_remark,
hrms_salary_deduction.`deduction_amount` AS deduction_amount
FROM `hrms_salary_payment`
LEFT JOIN `hrms_salary_additional` ON hrms_salary_additional.payment_id = hrms_salary_payment.payment_id
LEFT JOIN `hrms_salary_deduction` ON hrms_salary_deduction.payment_id = hrms_salary_payment.payment_id
where hrms_salary_payment.`payment_id` = 27
GROUP BY hrms_salary_payment.`payslip_no`, hrms_salary_additional.`item_remark`;

Related

Is it possible that each condition in "case when" has a different table?

I have a query like below
select
COALESCE(Clinic,'total') as Clinic,
sum(Non_Billable) as Non_Billable,
sum(initial_Non_Billable) as initial_Non_Billable,
sum(Non_Billable)/NULLIF(sum(initial_Non_Billable),0) as Non_Billable_initial_revenue
FROM (
select
businesses.label as Clinic,
sum(CASE
WHEN appointment_types.category IN (
'Others',
'Non-Billable')
and appointment_types.name like '%initial%'
then invoices.net_amount ELSE 0 END)
as Non_Billable,
count(CASE
WHEN appointment_types.category IN (
'Others',
'Non-Billable')
and appointment_types.name like '%initial%'
then appointment_types.name ELSE null END)
as initial_Non_Billable
FROM
individual_appointments
INNER join appointment_types on
appointment_types.id = individual_appointments.appointment_type_id
inner join invoices on
invoices.appointment_id = individual_appointments.id
inner join businesses on
businesses.id = individual_appointments.business_id
group by
businesses.label,
appointment_types.name,
appointment_types.category,
invoices.net_amount
)x
group by
ROLLUP(Clinic);
is it possible for each condition in "case when then" to have a different table?
example: for "Non_Billable" only want from individual_appointment, appointment_types, invoices and businesses table only.
while "initial_Non_Billable" only wants from individual_appointment, appointment_types, and businesses table.
can it be like that?
If possible, how? can anyone give an example?
From what I see, I suppose the problem here is that there can be many invoices per appointment, so when you join invoices you get appointments multifold which also multiplies your counts.
You don't really want to join invoices hence, but invoice sums. I.e. aggregate before joining.
Then, you are only interested in non-billable appointments, so you can put that criteria into your ON clauses and outer join in order to get clinics without such appointments.
select
coalesce(b.label, 'total') as clinic,
coalesce(sum(i.total_net_amount), 0) as initial_non_billable_sum,
count(at.id) as initial_non_billable_count,
avg(i.total_net_amount) as initial_non_billable_average
from businesses b
left join individual_appointments ia on ia.business_id = b.id
left join appointment_types at on at.id = ia.appointment_type_id
and at.category in ('others', 'non-billable')
and at.name like '%initial%'
left join
(
select appointment_id, sum(net_amount) as total_net_amount
from invoices
group by appointment_id
) i on i.appointment_id = ia.id
group by rollup(b.label)
order by b.label nulls last;

How to add the tax and then multiply with the price in mysql

I am trying to add the tax and multiply the result with a total price.
Here are the tables
"Charge" Table
Charge_Type
Tax_type
charge type tax list
I want to calculate the tax and the multiply with the amount for each charge_id
I tried attempting this way:
SELECT `charge_id` AS "Charge ID", SUM( tt.percentage ) AS "Tax"
FROM charge c, charge_type ct, tax_type tt, charge_type_tax_list cttl
WHERE tt.tax_type_id = cttl.tax_type_id
GROUP BY c.charge_type_id, c.charge_id
LIMIT 0 , 30
You are using a join syntax that was made redundant more than twenty years ago. Whichever book or class or tutorial has been teaching you this outdated syntax, quit it. This syntax is prone to errors, as your own query plainly shows. Your query translated to proper joins is:
SELECT `charge_id` AS "Charge ID", SUM( tt.percentage ) AS "Tax"
FROM charge c
CROSS JOIN charge_type ct
CROSS JOIN tax_type tt
INNER JOIN charge_type_tax_list cttl ON tt.tax_type_id = cttl.tax_type_id
GROUP BY c.charge_type_id, c.charge_id
LIMIT 0 , 30
You are combining all charge records with all charge_type records and all tax_type records. 6 x 3 x 3 = 54 records in your example. This makes no sense. You would want to join only related records in the first place.
What you really want to do is join charges with their tax sum:
select
c.charge_id,
tax.tax_sum,
c.amount,
c.amount * (1 + coalesce(tax.tax_sum, 0)) as taxed_amount
from charge c
left join
(
select
cttl.charge_type_id,
sum(tt.percentage) as tax_sum
from charge_type_tax_list cttl
join tax_type tt on tt.tax_type_id = cttl.tax_type_id
group by cttl.charge_type_id
) tax on tax.charge_type_id = c.charge_type_id;
You could do an INNER JOIN between the tables and calculate the corresponding percentage's grouped by charge id. The query below should do the trick:
SELECT charge.charge_type_id, (SUM(percentage) + 1) * charge.amount AS total_tax
FROM charge INNER JOIN charge_type ON charge.charge_type_id = charge_type.charge_type_id
INNER JOIN charge_type_tax_list ON charge_type.id = charge_type_tax_list.charge_type_id
INNER JOIN tax_type ON charge_type_tax_list.tax_type_id = tax_type.tax_type_id GROUP BY charges.id;

Inner join and left join not working as expected in mysql

I have 3 tables
table_supplier_bills - bill_id, supplier_id, date
table_supplier_bill_details - bill_id, product_id, quantity, rate
table_supplier_bill_payment_details - id, bill_id, payment_date, amount
I want to get all the bills with their bill_amount and paid_amount.
This is my query.
select
SB.bill_id,
SB.date, SB.supplier_id,
SUM(SBD.quantity * SBD.rate) as bill_amount,
COALESCE(SUM(SBPD.payment_amount), 0.00) as paid_amount
from table_supplier_bills SB
INNER JOIN
table_supplier_bill_details SBD
ON SB.bill_id = SBD.bill_id
LEFT JOIN table_supplier_bill_payment_details SBPD
ON SBD.bill_id = SBPD.bill_id
group by SBD.bill_id;
But this query doesn't give correct paid_amount if there are multiple rows in table_supplier_bill_details for a bill. in case of multiple rows query gives the paid_amount multiplied by as many rows are in table_supplier_bill_details for that table.
Can anyone help me what is wrong here?
Use a correlated query instead :
SELECT SB.bill_id,
SB.date,
SB.supplier_id,
SUM(SBD.quantity * SBD.rate) as bill_amount,
COALESCE((SELECT SUM(SBPD.payment_amount)
FROM table_supplier_bill_payment_details SBPD
WHERE SBD.bill_id = SBPD.bill_id ),0.00) as paid_amount
FROM table_supplier_bills SB
INNER JOIN table_supplier_bill_details SBD
ON SB.bill_id = SBD.bill_id
GROUP BY SBD.bill_id;

Create One Result set from 3 different Queries

I am trying to create a result set using three queries. I have three tables an inventory table, a form order table, and a form order detail table. I need to be able to input a date range and get how many forms were ordered, how many are in current inventory, and how many were destroyed based on if they contain a destruction date. Ultimately i want a result set that shows:
InventoryId, FormDescription, Product, Ordered, Shipped, Destroyed, Total ending
What would be the best way to get that result set using these queries?
These are my three Queries
SELECT FOD.InventoryId, SUM(FOD.FormOrderAmount) as totalOrdered, FOD.FormShippedAmount FROM tblFormOrder FMO
JOIN tblFormOrderDetails FOD ON FOD.FormOrderId = FMO.FormOrderId
WHERE FMO.OrderDateTime BETWEEN '20110101' and '20120101'
AND FMO.OrderStatus IN ('S')
GROUP BY FOD.InventoryId, FOD.FormShippedAmount -- total shipped by date and inventoryid
SELECT INV.InventoryId, SUM(INV.CurrentAmount) as currentAmount, SUM(INV.OrderAmount) as OrderAmount,
(SUM(INV.OrderAmount) - SUM(INV.CurrentAmount)) as InventoryUsed
FROM tblInventory INV
where INV.CreatedOn
BETWEEN '20110101' and '20120101'
GROUP BY INV.InventoryId -- current amount based off ordered and used
select INV.InventoryId, count(*) as total
, FMO.OrderDateTime as OrderDate, Inv.FormNo, INV.FormDescription, INV.Product
from [tblinventory] INV
join tblformorderdetails FOD ON FOD.InventoryId = inv.InventoryId
join tblformorder FMO on FMO.FormOrderId = FOD.FormOrderId
where INV.DestructionDate
BETWEEN '20110101' and '20120101'
group by
FMO.OrderDateTime,
Inv.FormNo, INV.FormDescription, INV.Product, INV.InventoryId -- using count to find how many destroyed if they have a destruction date
If you want an inner join you can do this
SELECT *
FROM (...) AS Q1, (...) AS Q2, (...) AS Q3
WHERE Q1.InventoryID = Q2.InventoryID AND Q2.InventoryID = Q3.InventoryID
This will only give you the InventoryIDs that are in all 3 queries.
You probably don't want this you probably want all inventory IDs... so you do this.
SELECT *
FROM (SELECT DISTINCT InventoryID FROM tblFormOrderDetails
UNION ALL
SELECT DISTINCT InventoryID FROM tblInventory) I
LEFT JOIN (...) Q1 ON I.InventoryID = Q1.InventoryId
LEFT JOIN (...) Q2 ON I.InventoryID = Q2.InventoryId
LEFT JOIN (...) Q3 ON I.InventoryID = Q3.InventoryId
Make each query a subquery that you join together.
SELECT *
FROM (
SELECT FOD.InventoryId, SUM(FOD.FormOrderAmount) as totalOrdered, FOD.FormShippedAmount FROM tblFormOrder FMO
JOIN tblFormOrderDetails FOD ON FOD.FormOrderId = FMO.FormOrderId
WHERE FMO.OrderDateTime BETWEEN '20110101' and '20120101'
AND FMO.OrderStatus IN ('S')
GROUP BY FOD.InventoryId, FOD.FormShippedAmount -- total shipped by date and inventoryid
) AS q1
LEFT JOIN (
SELECT INV.InventoryId, SUM(INV.CurrentAmount) as currentAmount, SUM(INV.OrderAmount) as OrderAmount,
(SUM(INV.OrderAmount) - SUM(INV.CurrentAmount)) as InventoryUsed
FROM tblInventory INV
where INV.CreatedOn
BETWEEN '20110101' and '20120101'
GROUP BY INV.InventoryId -- current amount based off ordered and used
) AS q2 ON q1.InventoryId = q2.InventoryId
LEFT JOIN (
select INV.InventoryId, count(*) as total
, FMO.OrderDateTime as OrderDate, Inv.FormNo, INV.FormDescription, INV.Product
from [tblinventory] INV
join tblformorderdetails FOD ON FOD.InventoryId = inv.InventoryId
join tblformorder FMO on FMO.FormOrderId = FOD.FormOrderId
where INV.DestructionDate
BETWEEN '20110101' and '20120101'
group by
FMO.OrderDateTime,
Inv.FormNo, INV.FormDescription, INV.Product, INV.InventoryId -- using count to find how many destroyed if they have a destruction date
) AS q3 ON q1.InventoryId = q3.InventoryId

MYSQL - JOIN table filter not working

I have four table each table connected with some id kindly see the below query how I'm getting
SELECT
tax_rates.name,
IF( products.tax_method = 0, 'Inclusive', 'Exclusive') AS type,
IF((SUM(purchases.grand_total) > 0),(SUM(purchases.grand_total)),(SUM(purchase_items .subtotal))) AS total_amount,
IF((SUM(purchases.order_tax) > 0),(SUM(purchases.order_tax)),SUM(purchase_items .item_tax)) AS tax_amount
FROM tax_rates
LEFT JOIN purchases ON purchases.order_tax_id = tax_rates.id
LEFT JOIN purchase_items ON purchase_items.tax_rate_id = tax_rates .id
LEFT JOIN products ON products.id = purchase_items.product_id
WHERE purchases.warehouse_id = 1
GROUP BY tax_rates.id, products.tax_method
ORDER BY tax_rates.name desc LIMIT 0, 10
The above query didn't return any result but if I remove WHERE purchases.warehouse_id = 1 then it display the result. I don't know where I'm doing the mistake. Kindly correct me.
Sorry to tell about this I'm try to get purchase order tax and purchase Item tax
in particular store and date
Output
name type total_amount tax_amount
VAT #20% Inclusive 11005.2000 1834.2000
VAT #10% Inclusive 165.0000 15.0000
No Tax Exclusive 204771.4000 0.0000
GST #6% Exclusive 7155.0000 405.0000
GST #6% Inclusive 7155.0000 405.0000
Thank you
Data type? purchases.warehouse_id = '1'?
You should not add the condition in where clause, when you are using the field of the left join table. so remove the where clause and use like below
LEFT JOIN purchases ON purchases.order_tax_id = tax_rates.id and purchases.warehouse_id = 1
If you try to add the left join table field in where clause it will become INNER JOIN. hence it may not display any rows according to your data.