Joining results of two independent query - mysql

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

Related

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

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....

Ho to get last item in mysql using max()

I want to get the last item as result using max(), but i'm just getting the first item even if im using max()
Here's the SQL code:
SELECT r.correct, r.items, r.percentage,MAX(r.date_taken) as date_taken,
u.username,u.FN, u.user_course_type,
IFNULL(u.user_major_type,'N/A') as user_major_type,u.level_name,
u.section_name
FROM bcc_fs_exam_result r
INNER JOIN
(SELECT u.id_user, u.username, CONCAT(u.lastname,', ',u.firstname) as FN,
c.user_course_type, m.user_major_type, l.level_name, s.section_name
FROM bcc_fs_user u
LEFT JOIN bcc_fs_user_course c on c.id_user_course = u.id_user_course
LEFT JOIN bcc_fs_user_major m on m.id_user_major = u.id_user_major
LEFT JOIN bcc_fs_group_level l ON l.id_level = u.id_level
LEFT JOIN bcc_fs_group_section s ON s.id_section = u.id_section
) u ON r.id_user = u.id_user WHERE r.id_exam = 5 GROUP BY r.id_user
TIA
What I take from your question is that you want to get the "correct", "items", "percentage" ect. columns of the row in bcc_fs_exam_result which has the last or first date.
If that's correct then you can filter bcc_fs_exam_result by first finding what is the min or max date by for each id_user then join that back on the exam results table.
SELECT
r.correct,
r.items,
r.percentage,
r.date_taken,
u.username,
u.FN,
u.user_course_type,
IFNULL(u.user_major_type,'N/A') as user_major_type,
u.level_name,
u.section_name
FROM bcc_fs_exam_result r
INNER JOIN (
SELECT u.id_user,
u.username,
CONCAT(u.lastname,', ',u.firstname) as FN,
c.user_course_type,
m.user_major_type,
l.level_name,
s.section_name
FROM bcc_fs_user u
LEFT JOIN bcc_fs_user_course c on c.id_user_course = u.id_user_course
LEFT JOIN bcc_fs_user_major m on m.id_user_major = u.id_user_major
LEFT JOIN bcc_fs_group_level l ON l.id_level = u.id_level
LEFT JOIN bcc_fs_group_section s ON s.id_section = u.id_section
) u ON r.id_user = u.id_user
INNER JOIN (
SELECT
id_user, max(r.date_taken) as last_date_taken
FROM bcc_fs_exam_result
GROUP BY id_user
) as lastdate ON lastDate.id_user = r.id_user and r.date_taken = lastdate.last_date_taken
which could be more simply written as :
SELECT
r.correct,
r.items,
r.percentage,
r.date_taken,
u.username,
CONCAT(u.lastname,', ',u.firstname) as FN,
c.user_course_type,
IFNULL(m.user_major_type,'N/A') as user_major_type,
l.level_name,
s.section_name
FROM bcc_fs_exam_result r
INNER JOIN (
SELECT
id_user, max(r.date_taken) as last_date_taken
FROM bcc_fs_exam_result
GROUP BY id_user
) as lastdate ON lastDate.id_user = r.id_user and r.date_taken = lastdate.last_date_taken
INNER JOIN bcc_fs_user u on r.id_user = u.id_user
LEFT JOIN bcc_fs_user_course c on c.id_user_course = u.id_user_course
LEFT JOIN bcc_fs_user_major m on m.id_user_major = u.id_user_major
LEFT JOIN bcc_fs_group_level l ON l.id_level = u.id_level
LEFT JOIN bcc_fs_group_section s ON s.id_section = u.id_section
You have assumed that id_user + date_taken is a surrogate key of bcc_fs_exam_result which you should probably enforce with a constraint if at all possible. Otherwise it looks from your sample data that the order of the unique id column id_result follows the date_takenso you might be better to use Max(id_result) rather than Max(date_taken). That would avoid returning duplicate rows for one id_user where two rows of bcc_fs_exam_result have the same taken_date and `id_user.

How do I get number of results (rows) in MySQL?

Normally the query below gives me only one result (row).
SELECT
`s`.`FIRMA_UNVANI` AS `FIRMA_UNVANI`,
`s`.`RECNO` AS `RECNO`,
`s`.`BOLGE` AS `BOLGE`,
`s`.`BOLGE_NO` AS `BOLGE_NO`,
`s`.`DURUM` AS `DURUM`,
l.ILCE,
IL.SEHIR,
count(i.recno) AS NUMBER_OF_WORKS
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
WHERE
1 = 1
GROUP BY
s.BOLGE
ORDER BY
IS_SAYISI
LIMIT 0,
15
I get only one result
+----------------+-------+------+---------+------+-----+----------+-----------------+
|FIRMA_UNVANI |RECNO |BOLGE |BOLGE_NO |DURUM |ILCE | SEHIR | NUMBER_OF_WORKS |
+----------------+-------+------+---------+------+-----+----------+-----------------+
|Pirana |2501 |Tekkt |58 |-1 |NT |Istanbul |1428 |
+----------------+-------+------+---------+------+-----+----------+-----------------+
Here the key is RECNO.
I want to count the results:
SELECT
count(0) AS _count
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
WHERE
1 = 1
GROUP BY
s.BOLGE
And I get this wired result:
1428
It was supposed to be 1. Isn't it?
The result is perfectly fine, since you are just counting a 0 for every row instead of i.recno, therefore both resulting in 1428.
To count the number of results, you could wrap your whole query like this to get a resultcount:
SELECT count(*) AS resultcount FROM (
SELECT
`s`.`FIRMA_UNVANI` AS `FIRMA_UNVANI`,
`s`.`RECNO` AS `RECNO`,
`s`.`BOLGE` AS `BOLGE`,
`s`.`BOLGE_NO` AS `BOLGE_NO`,
`s`.`DURUM` AS `DURUM`,
l.ILCE,
IL.SEHIR,
count(i.recno) AS NUMBER_OF_WORKS
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
GROUP BY
s.BOLGE
ORDER BY
IS_SAYISI
LIMIT 0, 15) AS temp
Also note, that WHERE 1=1 is not necessary.
You have used GROUP BY in your query so you will get each group count in result, For example if there 3 group then you will get 3 count result..
If you need to get count of result rows then please use sub query see below
SELECT count(0) AS _count FROM(
SELECT
*
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
WHERE
1 = 1
GROUP BY
s.BOLGE
) AS Temp;

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.

REGEX starts by Subquery

This is a query that i just made and it works correctly
select
sum(IF(l.bandera='DEBITO',l.valor,0)) totdebito,
sum(IF(l.bandera='CREDITO',l.valor,0)) totcredito ,n.nit_ID
from lineaasiento l left join clientesam c on c.Dk=l.clientesmayor_OID
left join proveedores p on p.Dk=l.proveedor_OID left join empleado e on e.Dk=l.empleado_OID
left join banco b on b.Dk=l.banco_OID left join cuentacontable cc on cc.Dk=l.cuentacontable_OID
left join nit n on n.Dk=coalesce(c.nit_OID,p.nit_OID,e.nit_OID,b.nit_OID,null)
where (timefcontable between '2013-01-01' and '2013-12-31') and
estadolinea_OID in (Select Dk from estadoasiento where codigo!=4) and
cc.cuentacontable_ID REGEXP '^5'
group by n.Dk
But, i have a problem right now... I need REGEX '^5' be a subquery sentence like this
select
sum(IF(l.bandera='DEBITO',l.valor,0)) totdebito,
sum(IF(l.bandera='CREDITO',l.valor,0)) totcredito ,n.nit_ID
from lineaasiento l left join clientesam c on c.Dk=l.clientesmayor_OID
left join proveedores p on p.Dk=l.proveedor_OID left join empleado e on e.Dk=l.empleado_OID
left join banco b on b.Dk=l.banco_OID left join cuentacontable cc on cc.Dk=l.cuentacontable_OID
left join nit n on n.Dk=coalesce(c.nit_OID,p.nit_OID,e.nit_OID,b.nit_OID,null)
where (timefcontable between '2013-01-01' and '2013-12-31') and
estadolinea_OID in (Select Dk from estadoasiento where codigo!=4) and
cc.cuentacontable_ID REGEXP (^a query that returns a lot of values and i need to get the elements that starts by this)
group by n.Dk
It is possible?
For building your regex...
select
'^(' || group_concat(my_value separator '|') || ')' as regex
from
my_table
NOTA: There is a 1024 bytes limit on results returned by group_concat. So if you expect larger results, run the following query before your final query (see below).
set group_concat_max_len=2048
Final query
select
sum(IF(l.bandera='DEBITO',l.valor,0)) totdebito,
sum(IF(l.bandera='CREDITO',l.valor,0)) totcredito ,
n.nit_ID
from
lineaasiento l
left join
clientesam c on c.Dk=l.clientesmayor_OID
left join
proveedores p on p.Dk=l.proveedor_OID
left join
empleado e on e.Dk=l.empleado_OID
left join
banco b on b.Dk=l.banco_OID
left join
cuentacontable cc on cc.Dk=l.cuentacontable_OID
left join
nit n on n.Dk=coalesce(c.nit_OID, p.nit_OID, e.nit_OID, b.nit_OID, null)
inner join
(select '^(' || group_concat(my_value separator '|') || ')' as regex from my_table) values
where
(
timefcontable between '2013-01-01' and '2013-12-31'
)
and estadolinea_OID in (
Select
Dk
from
estadoasiento
where
codigo!=4
)
and cc.cuentacontable_ID REGEXP values.regex
group by
n.Dk