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
Related
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;
I have a table that looks like this:
For each COMPANY there are multiple NATURAL_PERSON_ID, every NATURAL_PERSON have a date in which an audit was performed FECHA_DE_REPORTE and as a company there is a date in which the first loan was give to that company.
What I want is to select for each NATURAL_PERSON all the FOLIO_CONSULTA whose FECHA_DE_REPORTE is less or equal to FIRST_LOAN (the date in which the first loan was given for that company) Then I need to find the MAX date among each group and keep al the information (the whole row) for the value that fulfills all these conditions, and all this for each NATURAL_PERSON
So for this example the result I expected is all the information of the second row since this is the MAX() of FECHA_DE_REPORTE by COMPANY AND NATURAL_PERSON.
I have tried:
SELECT NPC.COMPANY_ID
,NPC.NATURAL_PERSON_ID
,NPS.DIGITAL_SIGNATURE_ID
,CDC.FOLIO_CONSULTA
,CDC.FECHA_DE_REPORTE
,FIRST_LOAN.FIRST_LOAN
,MAX(CDC.FECHA_DE_REPORTE) MAX_FOLIO_CONSUTA
FROM KONFIO.NATURAL_PERSON_COMPANY NPC
LEFT JOIN KONFIO.NATURAL_PERSON_SIGNATURE NPS ON NPS.NATURAL_PERSON_ID = NPC.NATURAL_PERSON_ID
JOIN KONFIO.CDC_RESPONSE CDC ON CDC.DIGITAL_SIGNATURE_ID= NPS.DIGITAL_SIGNATURE_ID
JOIN
(
SELECT CAPP.COMPANY_ID
,MIN(LOAN.DOCUMENTATION_DATE) FIRST_LOAN
FROM KONFIO.COMPANY_APPLICATION CAPP
JOIN KONFIO.LOAN ON LOAN.APPLICATION_ID = CAPP.APPLICATION_ID
GROUP BY CAPP.COMPANY_ID) FIRST_LOAN ON FIRST_LOAN.COMPANY_ID = NPC.COMPANY_ID
WHERE CDC.FECHA_DE_REPORTE <= FIRST_LOAN.FIRST_LOAN
AND NPC.COMPANY_ID IN (1033)
GROUP BY NPC.COMPANY_ID, NPC.NATURAL_PERSON_ID
but it retrieves the first value that finds so the FOLIO_CONSULTA does not correspond to the FOLIO_CONSULTA of the MAX() FECHA_DE_REPORTE
Any help would be appreciated
You should join the subquery for MAX(FECHA_DE_REPORTE) on table CDC_RESPONSE
SELECT NPC.COMPANY_ID
,NPC.NATURAL_PERSON_ID
,NPS.DIGITAL_SIGNATURE_ID
,CDC.FOLIO_CONSULTA
,CDC.FECHA_DE_REPORTE
,FIRST_LOAN.FIRST_LOAN
,T.MAX_FOLIO_CONSUTA
FROM KONFIO.NATURAL_PERSON_COMPANY NPC
INNER JOIN (
SELECT DIGITAL_SIGNATURE_ID
, MAX(FECHA_DE_REPORTE) MAX_FOLIO_CONSUTA
FROM KONFIO.CDC_RESPONSE
GROUP BY DIGITAL_SIGNATURE_ID
) T ON T.DIGITAL_SIGNATURE_ID = NPS.DIGITAL_SIGNATURE_ID
AND T.MAX_FOLIO_CONSUTA = CDC.FECHA_DE_REPORTE
LEFT JOIN KONFIO.NATURAL_PERSON_SIGNATURE NPS ON NPS.NATURAL_PERSON_ID = NPC.NATURAL_PERSON_ID
JOIN KONFIO.CDC_RESPONSE CDC ON CDC.DIGITAL_SIGNATURE_ID= NPS.DIGITAL_SIGNATURE_ID
JOIN
(
SELECT CAPP.COMPANY_ID
,MIN(LOAN.DOCUMENTATION_DATE) FIRST_LOAN
FROM KONFIO.COMPANY_APPLICATION CAPP
JOIN KONFIO.LOAN ON LOAN.APPLICATION_ID = CAPP.APPLICATION_ID
GROUP BY CAPP.COMPANY_ID) FIRST_LOAN ON FIRST_LOAN.COMPANY_ID = NPC.COMPANY_ID
WHERE CDC.FECHA_DE_REPORTE <= FIRST_LOAN.FIRST_LOAN
AND NPC.COMPANY_ID IN (1033)
GROUP BY NPC.COMPANY_ID, NPC.NATURAL_PERSON_ID
...... missing part
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;
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`;
I have this query
SELECT salary
FROM worker W
JOIN single_user U ON u.users_id_user = W.single_user_users_id_user
JOIN university_has_single_user US ON US.single_user_users_id_user = U.users_id_user
JOIN course C ON C.id_course = US.course_id_course
JOIN formation_area FA ON FA.id_formation_area = C.formation_area_id_formation_area
WHERE FA.area = "Multimédia"
GROUP BY users_id_user
...that gave this output:
salary
--------
1400.00
800.00
How can I calculate the avg of this output? If I add:
SELECT round(avg (salary), 0)
...the output is again 1400.00 and 800.00, not the avg (because the group by).
Use:
SELECT AVG(DISTINCT salary)
FROM worker W
JOIN single_user U ON u.users_id_user = W.single_user_users_id_user
JOIN university_has_single_user US ON US.single_user_users_id_user = U.users_id_user
JOIN course C ON C.id_course = US.course_id_course
JOIN formation_area FA ON FA.id_formation_area = C.formation_area_id_formation_area
WHERE FA.area = "Multimédia"
Because the salary column is not wrapped in an aggregate, per the documentation, the values you see are arbitrary (can't be guaranteed 100% of the time).
Usually, you'd need a derived table to get the average of the distinct values but MySQL's AVG supports using DISTINCT within it.