How can i eliminate duplicate data when joining 2 queries via union? - mysql

i have 2 queries that pull same fields with only diff is what the subquery in the where clause returns.
first query pulls based on the code and insurance_group_name
SELECT
cpt_codes.code,
ii.insurance_group_name,
ii.insurance_group_id,
CAST(AVG(dcc_total_view.allowedAmount) AS decimal(10, 2)) `AVG Allowed by Group Name`,
CAST(AVG(rc_total_view.runningCollectedReceivedByProvider) AS decimal(10, 2)) `AVG Collected by Group Name`,
GROUP_CONCAT(DISTINCT file_acceptance) AS `FAN`
FROM ds
LEFT OUTER JOIN dd
ON ds.dos_detail_id = dd.id
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cpt_codes
ON dcc.cpt_id = cpt_codes.id
LEFT OUTER JOIN bi
ON ds.billing_id = bi.id
LEFT OUTER JOIN cs
ON bi.claim_status = cs.id
LEFT OUTER JOIN rc_total_view
ON ds.payment_information_id = rc_total_view.id
LEFT OUTER JOIN dcc_total_view
ON ds.id = dcc_total_view.dos_id
WHERE (cpt_codes.code, ii.insurance_group_name) IN (SELECT
cpt_codes.code,
ii.insurance_group_name
FROM ds
LEFT OUTER JOIN dd
ON ds.dos_detail_id = dd.id
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cpt_codes
ON dcc.cpt_id = cpt_codes.id
LEFT OUTER JOIN bi
ON ds.billing_id = bi.id
LEFT OUTER JOIN cs
ON bi.claim_status = cs.id
WHERE cs.status = 'Pending'
AND date_of_service BETWEEN '2017/01/01' AND '2018/08/31'
AND (dcc.rev_code = '0490'
OR dcc.rev_code = '0360'))
AND date_of_service BETWEEN '2017/01/01' AND '2018/08/31'
AND (dcc.rev_code = '0490'
OR dcc.rev_code = '0360')
AND dcc_total_view.allowedAmount > 0
GROUP BY code ,insurance_group_name
this would return a line like this
code
insurance_group_name
insurance_group_id
AVG Allowed by Group Name
AVG Collected by Group Name
FAN
20553
AE
215825
1440.97
889.48
DELA081518,MOLDGILR919,SHIC060618,MANS072718,DELA053018,DELS072518
the Second one pulls based on insurance_group_id
SELECT
cpt_codes.code,
ii.insurance_group_name,
ii.insurance_group_id,
CAST(AVG(dcc_total_view.allowedAmount) AS decimal(10, 2)) `AVG Allowed by Group Name`,
CAST(AVG(rc_total_view.runningCollectedReceivedByProvider) AS decimal(10, 2)) `AVG Collected by Group Name`,
GROUP_CONCAT(DISTINCT file_acceptance) AS `FAN`
FROM ds
LEFT OUTER JOIN dd
ON ds.dos_detail_id = dd.id
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cpt_codes
ON dcc.cpt_id = cpt_codes.id
LEFT OUTER JOIN bi
ON ds.billing_id = bi.id
LEFT OUTER JOIN cs
ON bi.claim_status = cs.id
LEFT OUTER JOIN rc_total_view
ON ds.payment_information_id = rc_total_view.id
LEFT OUTER JOIN dcc_total_view
ON ds.id = dcc_total_view.dos_id
WHERE (cpt_codes.code, ii.insurance_group_id) IN (SELECT
cpt_codes.code,
ii.insurance_group_id
FROM ds
LEFT OUTER JOIN dd
ON ds.dos_detail_id = dd.id
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cpt_codes
ON dcc.cpt_id = cpt_codes.id
LEFT OUTER JOIN bi
ON ds.billing_id = bi.id
LEFT OUTER JOIN cs
ON bi.claim_status = cs.id
WHERE cs.status = 'Pending'
AND date_of_service BETWEEN '2017/01/01' AND '2018/08/31'
AND (dcc.rev_code = '0490'
OR dcc.rev_code = '0360'))
AND date_of_service BETWEEN '2017/01/01' AND '2018/08/31'
AND (dcc.rev_code = '0490'
OR dcc.rev_code = '0360')
AND dcc_total_view.allowedAmount > 0
GROUP BY code ,insurance_group_id
this would return a line like
code
insurance_group_name
insurance_group_id
AVG Allowed by Group Name
AVG Collected by Group Name
FAN
20553
AE
10198703100012
250.25
150.36
MOLDGILR919
when doing union on these 2 i find some data is duplicated where the FAN # that the second query returns is included in the output from the first as you can see the FAN# is part of the ones that make up the results of the first script.
how can i join together the results of these 2 queries and make sure if the FAN# in the second is already included in results from the first for a given code (like 20553 in the example) then that row from the second will not be included in the final output ?
I hope i have included enough info and detail to help me out here, I really appreciate any help to figure this out.

Put the output of your first statemen in a temporary table, lets name that #temp1, and the output of your second query in a temporary table named #temp2.
After that you can do:
SELECT *
FROM #temp1
UNION ALL
SELECT *
FROM #temp2
WHERE code NOT IN (SELECT code FROM #temp1)
EDIT: Because of the FAN problem..
I think you should change your queries, in this way:
Do not use GROUP_CONCAT(...) to combine the results of different FAN's in one row, and add file_acceptance to the GROUP BY-clause
This way you will get indivdual records for every FAN, annd, after the UNION ALL you can GROUP_CONCAT() then again.
This might need some more think/tweak work because of the AVG() fields....

Related

how best to use list of codes from sql query as input for another query

I have couple of SQL im trying to use together to generate a report showing the AVG amount for 2 fields for a given code that i want to extract from the other query. So this query returns the list of codes
SELECT DISTINCT
cc.code AS `CC Code`
FROM ds
LEFT OUTER JOIN dd
ON ds.dd_id = dd.id
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cc
ON dcc.cpt_id = cc.id
LEFT OUTER JOIN bi
ON ds.bi_id = bi.id
LEFT OUTER JOIN cs
ON bi.claim_status = cs.id
WHERE ii.company = "Alpha"
AND cs.status = "On HOLD"
AND dcc.amount_allowed > 0
this returns a list of about 25 unique codes. i then run this one manually plugging in each of those to get the avg amounts for 2 fields that use that code.
SELECT
cc.code AS `CC Code`,
CAST(AVG(dcc.amount_allowed) AS decimal(10, 2)) `AVG Allowed`,
CAST(AVG(dcc.paid_amount) AS decimal(10, 2)) `Paid Avg`,
ii.company AS `I Company`
FROM ds
LEFT OUTER JOIN dd
ON ds.dd_id = dd.id
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cc
ON dcc.cpt_id = cc.id
LEFT OUTER JOIN bi
ON ds.bi_id = bi.id
WHERE ii.company = "Alpha"
AND code = '35647'
AND dcc.amount_allowed > 0
which returns results like
CC Code
AVG Allowed
Paid Avg
Insurance Company
35647
9373.44
8652.30
Alpha
i would like to just run it have it pass each of the codes and return the results for each code.
How would be best to go about doing this ?
Thanks for any help
Let's try to focus on what you're trying to get first. Forget all the other tables that are not used in the query; either in SELECT or WHERE. For example:
SELECT
cc.code AS `CC Code`,
CAST(AVG(dcc.amount_allowed) AS decimal(10, 2)) `AVG Allowed`,
CAST(AVG(dcc.paid_amount) AS decimal(10, 2)) `Paid Avg`,
ii.company AS `I Company`
FROM ds
/* comment out this part
LEFT OUTER JOIN dd
ON ds.dd_id = dd.id */
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cc
ON dcc.cpt_id = cc.id
/* comment out this part
LEFT OUTER JOIN bi
ON ds.bi_id = bi.id*/
WHERE ii.company = "Alpha"
AND code = '35647'
AND dcc.amount_allowed > 0
Then based on your condition "I would like to just run it have it pass each of the codes and return the results for each code", modify the query to something like this:
SELECT
cc.code AS `CC Code`,
CAST(AVG(dcc.amount_allowed) AS decimal(10, 2)) `AVG Allowed`,
CAST(AVG(dcc.paid_amount) AS decimal(10, 2)) `Paid Avg`,
ii.company AS `I Company`
FROM ds
LEFT OUTER JOIN ii
ON ds.ii_id = ii.id
LEFT OUTER JOIN dcc
ON ds.id = dcc.dos_id
LEFT OUTER JOIN cc
ON dcc.cpt_id = cc.id
WHERE dcc.amount_allowed > 0
GROUP BY cc.code, ii.company;
*commented out part omitted here for better view.
*removed > WHERE ii.company = "Alpha" AND code = '35647'.
Since you have an aggregation (AVG()), any non-aggregated column(s) in SELECT should be in the GROUP BY.
In case for ii.company, a few options:
If you don't want it, remove it from SELECT and GROUP BY.
If you don't really care what ii.company returns, you can change it to ANY_VALUE(ii.company) and retain it in GROUP BY.
If you want to show everything in ii.company attached to a single cc.code, you can change to GROUP_CONCAT(DISTINCT ii.company) and remove it from GROUP BY.
See if this will work out for you.

how do create a where clause to return if any of the columns in where cluase have active=1

I have an SQL query like below which has a where clause as WHERE pg.active=1 AND tcg.active=1 AND tpg.active=1,issue right now is that one or all of pg.active tcg.active ,tpg.active is set to 1 at any time,in the case where one of these is not set to 1 query doesn't return anything.
How do I change the where clause to return if any of pg.active tcg.active ,tpg.active is set to 1?
SELECT
..........
FROM software_products_software_images spsi
INNER JOIN software_images si ON si.software_image_id = spsi.software_image_id
INNER JOIN software_products sp ON sp.id = spsi.software_product_id
LEFT JOIN software_products_software_images_testplan_gate tpg ON tpg.software_products_software_images_id = spsi.Id
LEFT JOIN test_suites tp ON tp.id = tpg.testplan_id
LEFT JOIN software_products_software_images_testcase_gate tcg ON tcg.software_products_software_images_id = spsi.Id
LEFT JOIN test_cases tc ON tc.id = tcg.testcase_id
LEFT JOIN test_suites ts ON ts.id = tc.test_suite_id
LEFT JOIN software_products_software_images_percentage_gate pg ON pg.software_products_software_images_id = spsi.Id
...........................
WHERE pg.active=1 AND tcg.active=1 AND tpg.active=1
AND si.software_image='NHSS.QSDK.7.0.1' ORDER BY si.software_image, ts.suite_name
I believe you need to encapsulate the OR part of the WHERE statement in round brackets so that it returns a TRUE on any OR match along with your other conditions.
SELECT
..........
FROM software_products_software_images spsi
INNER JOIN software_images si ON si.software_image_id = spsi.software_image_id
INNER JOIN software_products sp ON sp.id = spsi.software_product_id
LEFT JOIN software_products_software_images_testplan_gate tpg ON tpg.software_products_software_images_id = spsi.Id
LEFT JOIN test_suites tp ON tp.id = tpg.testplan_id
LEFT JOIN software_products_software_images_testcase_gate tcg ON tcg.software_products_software_images_id = spsi.Id
LEFT JOIN test_cases tc ON tc.id = tcg.testcase_id
LEFT JOIN test_suites ts ON ts.id = tc.test_suite_id
LEFT JOIN software_products_software_images_percentage_gate pg ON pg.software_products_software_images_id = spsi.Id
...........................
WHERE (pg.active=1 OR tcg.active=1 OR tpg.active=1)
AND si.software_image='NHSS.QSDK.7.0.1' ORDER BY si.software_image, ts.suite_name

SUM is returning double value with multiple left joins

I've a SQL query in which SUM aggregate function returns all values just double. I exactly not understand, how it is happening. Here is the query
SELECT
st.id,
u.id AS user_id,
st.student_code,
spd.first_name,
spd.middle_name,
spd.last_name,
spd.birth_date,
classes.`class_name`,
sections.`section_name`,
sed.`roll_no`,
sgd.first_name AS gardian_first_name,
sgd.middle_name AS gardian_middle_name,
sgd.last_name AS gardian_last_name,
sgd.contact_no,
SUM(sfd.`final_fee`) AS total_calculated_fee,
SUM(sfd.`total_paid_amount`) AS total_paid_amount,
SUM(sfd.`total_due_amount`) AS total_due_amount
FROM
students st
LEFT JOIN users u
ON st.`id` = u.`student_id`
LEFT JOIN student_personal_details spd
ON st.`id` = spd.`student_id`
LEFT JOIN student_gardian_details sgd
ON st.`id` = sgd.`student_id`
LEFT JOIN student_education_details sed
ON st.`id` = sed.`student_id`
LEFT JOIN student_hostel_details shd
ON st.`id` = shd.`student_id`
LEFT JOIN classes
ON sed.`class_id` = classes.`class_id`
LEFT JOIN sections
ON sed.`section_id` = sections.`id`
LEFT JOIN student_fee_details sfd
ON st.`id` = sfd.`student_id`
WHERE st.is_active = 1 AND st.`id` = 2
GROUP BY sfd.`student_id`
LIMIT 0, 10
I used distinct in all three fields but the middle one is returning 1/4 value.
Could anyone help me

MS-Access Joining 2 Subqueries

Need a little help with subqueries
If I have a 1 query like this:
SELECT Learner.Learner_Id, Max(LearnerEmploymentStatus.DateEmpStatApp) AS LatestEmpDate, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON LearnerEmploymentStatus.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id
WHERE EmploymentStatusMonitoring.ESMType="BSI"
GROUP BY Learner.Learner_Id, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType
...and another like this:
SELECT Learner.Learner_Id, LearnerEmploymentStatus.DateEmpStatApp, EmploymentStatusMonitoring.ESMCode
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON Learner.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id
...and I wanted to do a join between the 2 queries (LEFT JOIN on the common Learner_Id and LatestEmpDate / DateEmpStatApp fields), how would I go about doing all this work in a single query where the 2 queries above would be subqueries?
My attempt below is not being accepted (JOIN expression not supported):
SELECT sQ1.Learner_Id, sQ1.LearnRefNumber, sQ1.FamilyName, sQ1.GivenNames, sQ1.LatestEmpDate, sQ1.ESMType, sQ2.ESMCode
FROM
(SELECT Learner.Learner_Id, Max(LearnerEmploymentStatus.DateEmpStatApp) AS LatestEmpDate, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON LearnerEmploymentStatus.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id
WHERE EmploymentStatusMonitoring.ESMType="BSI"
GROUP BY Learner.Learner_Id, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType) As sQ1
LEFT JOIN
(SELECT Learner.Learner_Id, LearnerEmploymentStatus.DateEmpStatApp, EmploymentStatusMonitoring.ESMCode
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON Learner.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id) As sQ2
ON (sQ1.Learner_Id = sQ2.Learner_Id) AND (sQ1.LatestEmpDate = sQ2.DateEmpStatApp);
Would something like this get you what you want...?
SELECT l.Learner_Id, d.LatestEmpDate, l.LearnRefNumber, l.FamilyName, l.GivenNames, m.ESMType, m.ESMCode
FROM ((Learner AS l
LEFT JOIN (
SELECT s.Learner_Id, MAX(s.DateEmpStatApp) AS LatestEmpDate
FROM LearnerEmploymentStatus AS s
GROUP BY s.Learner_Id) AS d ON d.Learner_Id = l.Learner_Id)
LEFT JOIN LearnerEmploymentStatus AS ls ON (ls.Learner_Id = d.Learner_Id) AND (ls.DateEmpStatApp = d.LatestEmpDate))
LEFT JOIN EmploymentStatusMonitoring AS m ON m.LearnerEmploymentStatus_Id = ls.LearnerEmploymentStatus_Id
WHERE m.ESMType = 'BSI'
Assumes the same learner won't have the same DateEmpStatApp twice, which may or not be valid.

Joining results of two independent query

I have two working queries:
1st returns the product list:
$sql = "
SELECT a.stockID, a.stockCatID, a.stockName, a.stockCode, a.stockCatCode,
CONCAT_WS(' » ', d.stockCatName, c.stockCatName, b.stockCatName) AS stockPath,
a.stockName AS stockTitle, a.stockID AS uniStock
FROM stockcards a
LEFT OUTER JOIN stockcategories b
ON a.stockCatID = b.stockCatID
LEFT OUTER JOIN stockcategories c
ON b.stockParentCat = c.stockCatID
LEFT OUTER JOIN stockcategories d
ON c.stockParentCat = d.stockCatID ";
2nd is basically returns the difference of total received and total sent whic is remaining quantity:
SELECT DISTINCT (COALESCE(o.totalReceived, 0) + COALESCE(p.totalSent, 0)) as RemainingStock
FROM deliverydetails k
INNER JOIN stockcards l ON k.stockID= l.stockID
LEFT JOIN
(
SELECT m.stockID, SUM(m.dQuantity) totalReceived
FROM deliverydetails m
WHERE m.dQuantity > 0
GROUP BY m.stockID
)
o ON k.stockID = o.stockID
LEFT JOIN
(
SELECT n.stockID, SUM(n.dQuantity) totalSent
FROM deliverydetails n
WHERE n.dQuantity < 0
GROUP BY n.stockID
)
p ON k.stockID = p.stockID
I need to add a new column to first query to display remanining quantity. But couldn't succeed to join this two. Thanks for any tip.
As it seems that your 2nd query just sums positive and negative dQuantities for each stockID, and then adds them together, I think this small change to your 1st query is
all that is needed:
SELECT a.stockID, a.stockCatID, a.stockName, a.stockCode, a.stockCatCode,
CONCAT_WS(' » ', d.stockCatName, c.stockCatName, b.stockCatName) AS stockPath,
a.stockName AS stockTitle, a.stockID AS uniStock,
dd.RemainingStock AS RemainingStock
FROM stockcards a
LEFT OUTER JOIN stockcategories b
ON a.stockCatID = b.stockCatID
LEFT OUTER JOIN stockcategories c
ON b.stockParentCat = c.stockCatID
LEFT OUTER JOIN stockcategories d
ON c.stockParentCat = d.stockCatID
LEFT OUTER JOIN
(SELECT stockID, SUM(dQuantity) AS RemainingStock
FROM deliverydetails
GROUP BY stockID) AS dd
ON dd.stockID = a.stockID