I need help. how can I convert this MySQL query count into MsSQL query
SELECT patientmasters.ID,
patientmasters.HRN,
patientmasters.LastName,
patientmasters.FirstName,
patientmasters.MiddleName,
count(casehistories.PatientID) as NumberOfRecords
from patientmasters
left join casehistories
on (patientmasters.ID = casehistories.PatientID)
group by
patientmasters.ID;
This answer could be useful.
For MS SQL Server it should be:
SELECT patientmasters.ID,
patientmasters.HRN,
patientmasters.LastName,
patientmasters.FirstName,
patientmasters.MiddleName,
count(casehistories.PatientID) as NumberOfRecords
from patientmasters
left join casehistories
on (patientmasters.ID = casehistories.PatientID)
group by
patientmasters.ID,
patientmasters.HRN,
patientmasters.LastName,
patientmasters.FirstName,
patientmasters.MiddleName;
In either database, I would recommend a correlated subquery:
select pm.*,
(select count(*)
from casehistories ch
where pm.ID = ch.PatientID
) as NumberOfRecords
from patientmasters pm;
In particular, both databases will take advantage of an index on casehistories(PatientID). This should have better performance by avoiding the outer aggregation.
Related
How to reduce the query execution time in mysql where table having records greater than 154381 and inner query should be used
This is my Query :
SELECT txn_gallery.gallery_image
FROM txn_gallery
WHERE villa_id IN(SELECT villa_id
FROM txn_notifications
LEFT JOIN mst_villa on mst_villa.sk_villa_id=txn_notifications.villa_id
WHERE txn_notifications.member_id='235' and txn_notifications.tran_status='Approved')
Your query is functionally identical to:
SELECT g.gallery_image
FROM txn_gallery g
JOIN txn_notifications n
ON n.villa_id = g.villa_id
WHERE n.member_id = 235
and n.tran_status = 'Approved'
An index on some combination of (villa_id,member_id,tran_status) would be useful
Its better to use join instead of inner query
JOIN can be faster than an equivalent subquery because the server might be able to optimize it better
So subqueries can be slower than LEFT [OUTER] JOIN
How can I turn this subquery in a JOIN?
I read that subqueries are slower than JOINs.
SELECT
reklamation.id,
reklamation.titel,
(
SELECT reklamation_status.status
FROM reklamation_status
WHERE reklamation_status.id_reklamation = reklamation.id
ORDER BY reklamation_status.id DESC
LIMIT 1
) as status
FROM reklamation
WHERE reklamation.aktiv=1
This should do it:
SELECT r.id, r.titel, MAX(s.id) as status
FROM reklamation r
LEFT JOIN reklamation_status s ON s.id_reklamation = r.id
WHERE r.aktiv = 1
GROUP BY r.id, r.titel
The key point here is to use aggregation to manage the cardinality between reklamation and reklamation_status. In your original code, the inline subquery uses ORDER BY reklamation_status.id DESC LIMIT 1 to return the highest id in reklamation_status that corresponds to the current reklamation. Without aggregation, we would probably get multiple records in the resultset for each reklamation (one for each corresponding reklamation_status).
Another thing is to consider is the type of the JOIN. INNER JOIN would filter out records of reklamations that do not have a reklamation_status: the original query with the inline subquery does not behave like that, so I chose LEFT JOIN. If you can guarantee that every reklamation has at least one child in reklamation_status, you can safely switch back to INNER JOIN (which might perform more efficiently).
PS:
I read that subqueries are slower than JOINs.
This is not a universal truth. It depends on many factors and cannot be told without seeing your exact use case.
Using JOIN query can be rewritten to:
SELECT reklamation.id, reklamation.titel, reklamation_status.status
FROM reklamation
JOIN reklamation_status ON reklamation_status.id_reklamation = reklamation.id
WHERE reklamation.aktiv=1
What you read is incorrect. Subqueries can be slower, faster, or the same as joins. I would write the query as:
SELECT r.id, r.titel,
(SELECT rs.status
FROM reklamation_status rs
WHERE rs.id_reklamation = r.id
ORDER BY rs.id DESC
LIMIT 1
) as status
FROM reklamation r
WHERE r.aktiv = 1;
For performance, you want an index on reklamation_status(id_reklamation, id, status).
By the way, this is a case where the subquery is probably the fastest method for expressing this query. If you attempt a JOIN, then you need some sort of aggregation to get the most recent status. That can be expensive.
How to convert the code below from Oracle 8i to MySQL-
select count(*)
from patient_visit,
organization_master
where patient_visit.organization_id=organization_master.organization_id(+);
In the where statement "organization_master.organization_id(+)" is not working in MySQL.
Pls suggest.
The (+) is an Oracle-specific notation for an outer join.
I think you should write something like this
select count(*)
FROM patient_visit
LEFT OUTER JOIN organization_master
ON patient_visit.organization_id=organization_master.organization_id
I haven't tested it since I have no data to test it but it should work.
Hope it helps
You would need to use the standard JOIN syntax which is supported by all modern SQL databases (also Oracle):
select count(*)
from patient_visit
left join organization_master
on patient_visit.organization_id = organization_master.organization_id
If you have other joins without the (+), then just replace those with inner join: avoid the comma completely in the from clause. Other, non-join conditions just stay in the where clause.
For example:
select count(*)
from patient_visit
inner join patient_registration
on patient_registration.pprn_regd_id = patient_visit.pprn_regd_id
left join organization_master
on patient_visit.com_organization_id = organization_master.com_organization_id
where patient_visit.ghm_hosp_id = i_hosp_id
I convert an old software (that use MS-ACCESS MDB) to mySQL.
I have a query that takes long time to run (actualy I break running after 5 minutes of waiting)
How can I write it?
SELECT pa_ID, pa_PRODUCT_ID, pr_ID,pr_NAME,Sum(pa_KILOS) as IN_KILOS,
(select sum(pl_KILOS) from POLHSH where POLHSH.pl_PRODUCT_ID = pa_PRODUCT_ID and POLHSH.pl_PARALABH_ID = pa_ID) as OUT_KILOS From PARALABH, PRODUCTS WHERE pa_company_id=1 GROUP BY pa_ID, pa_PRODUCT_ID,pr_ID, pr_NAME HAVING pa_ID=241 and pr_id=pa_PRODUCT_ID
Thanks in advance
Consider avoiding the correlated subquery which runs a SUM separately for each row and use a join of two aggregate queries each of which runs SUM once by grouping fields. Additionally, use explicit joins, the current SQL standard in joining tables/views.
Please adjust column aliases and names to actuals as assumptions were made below.
SELECT t1.*, t2.OUT_KILOS
FROM
(SELECT pa.pa_ID,
pa.pa_PRODUCT_ID,
pr.pr_ID,
pr.pr_NAME,
SUM(pa.pa_KILOS) AS IN_KILOS
FROM PARALABH pa
INNER JOIN PRODUCTS pr
ON pr.pr_id = pa.pa_PRODUCT_ID
WHERE pa.pa_company_id = 1
GROUP BY pa.pa_ID,
pa.pa_PRODUCT_ID,
pr.pr_ID,
pr.pr_NAME
HAVING pa.pa_ID = 241
) AS t1
INNER JOIN
(SELECT POLHSH.pl_PRODUCT_ID,
POLHSH.pl_PARALABH_ID
SUM(pl_KILOS) As OUT_KILOS
FROM POLHSH
GROUP BY POLHSH.pl_PRODUCT_ID,
POLHSH.pl_PARALABH_ID
) AS t2
ON t2.pl_PRODUCT_ID = t1.pa_PRODUCT_ID
AND t2.pl_PARALABH_ID = t1.pa_ID
I am trying to compare values against same table which has more than 1,000,000 rows. Below is my query and it takes around 25 secs to get results.
EXPLAIN SELECT DISTINCT a.studyid,a.number,a.load_number,b.studyid,b.number,b.load_number FROM
(SELECT t1.*, buildnumber,platformid FROM t t1
INNER JOIN testlog t2 ON t1.`testid` = t2.`testid`
WHERE (buildnumber =1031719 AND platformid IN (SELECT platformid FROM platform WHERE platform.`Description` = "Windows 7 SP1"))
)AS a
JOIN
(SELECT t1.*,buildnumber,platformid FROM t t1
INNER JOIN testlog t2 ON t1.`testid` = t2.`testid`
WHERE (buildnumber =1030716 AND platformid IN (SELECT platformid FROM platform WHERE platform.`Description` = "Windows 7 SP1"))
)AS b
ON a.studyid=b.studyid AND a.load_number = b.load_number AND a.number = b.number
Could you anyone help me to improve this query to get fast enough results?
The problem here is even I have number and load_number index, the query doesn't use that. I dont know why it is always ignored..
Thanks.
First, you have a silly query. You are retrieving six columns, but there are only three values. Look at the on clause.
I think your best bet is to rewrite the query using conditional aggregation. I think the following is equivalent:
SELECT t1.studyid, t1.load_number, t1.number
FROM t t1 INNER JOIN
testlog t2
ON t1.testid = t2.testid
WHERE t2.buildnumber IN (1031719, 1030716) AND
platformid IN (SELECT platformid FROM platform p WHERE p.Description = 'Windows 7 SP1'))
GROUP BY studyid, load_number, number
HAVING MIN(buildnumber) <> MAX(buildnumber)
For this query, you want indexes on platform(Description, platformid) and testlog(buildnumber, platformid) and t(testid).
Problem #1:
IN ( SELECT ... ) optimizes very poorly. The subquery is rerun again and again. It looks like you are expecting exactly one id from that query; if so, change it to = ( SELECT ... ). That way it will be run exactly once.
Problem #2:
FROM ( SELECT ... )
JOIN ( SELECT ... ) ON ...
optimizes poorly because neither subquery. Can you merge the two subqueries into one, as Gordon was trying? If not, then put one of them into a TEMPORARY TABLE and add an appropriate index to that table so that the ON will be able to use it. Probably PRIMARY KEY(studyid, load_number, number).
Footnote: The latest versions of MySQL have made improvements on these problems by dynamically generating indexes. What version are you using?