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
Related
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.
I'm trying to study SQL.
I have a problem with JOIN
I want to display ref_id, pro_name, class_name but I couldn't.
I find EFFICIENT solution.
MY QUERY (DOESN'T WORK)
SELECT
ref_id, pro_name, class_name
FROM
RC, RP, PP, LP
WHERE
RC.ref_id = RP.ref_id
Avoid using commas be CROSS JOIN
You could use JOIN to instead of commas
like this.
SELECT
RP.ref_id, PP.pro_name, LP.class_name
FROM
RP
LEFT JOIN RC ON RC.ref_id = RP.ref_id
LEFT JOIN PP ON PP.pro_id = RP.pro_id
LEFT JOIN LP ON LP.lec_id = RP.lec_id
Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax.
You would seem to want:
select rp.pro_id, pp.pro_name, lp.class_name
from rp left join
pp
on rp.pro_id = pp.pro_id left join
lp
on rp.lec_id = lp.lec_id;
Note the use of left join. This ensure that all rows are in the result set, even when one or the other joins doesn't find a matching record.
From what I can see, the table rc is not needed to answer this specific question.
I have a query where I am using a full outer join. But in some instance,
it gives me a syntax error.
What could be the reason for this? I don't see any miscode in my query.
MySQL does not support full outer join, but you can simulate it as a union between a left and right join query:
SELECT * FROM pbsdev3.item t1
LEFT JOIN pbsdev3.item_ledger_entry t2 ON t1.No_ = t2.Item_No_
UNION ALL
SELECT * FROM pbsdev3.item t1
RIGHT JOIN pbsdev3.item_ledger_entry t2 ON t1.No_ = t2.Item_No_
WHERE t1.No_ IS NULL
Note that in general if you find yourself doing full outer joins often, it could imply that your keys and data model are not well defined. One reason why MySQL does not support full joins could be that you should not have to use it.
Full outer join is quite a pain in MySQL. The first thing I would note is that it should not be needed. The items should match in the two tables, so an inner join or left join should be sufficient:
SELECT i.*, ile.*
FROM pbsdev3.item i LEFT JOIN
pbsdev3.item_ledger_entry ile
ON i.No_ = ile.Item_No_;
If you really need full outer join, then gather together all the items and use left join:
select it.*, ile.*
from (select i.No_ from item i union
select ile.Item_No_ from item_ledger_entry ile
) i left join
item it
on it.No_ = i.No_ left join
item_ledger_entry ile
on ile.No = i.No;
I can't for the life of me get this statement to work.
SELECT max(pm.timestamp), pm.id, pm.p_media_user_id, pm.p_media_type,
pm.p_media_file, pm.wall_post, pm.p_media_location,pm.p_media_location_name,
pm.p_media_category, pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id,
pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image
FROM p_media as pm
INNER JOIN p_users as pu ON pm.p_media_user_id = pu.fb_id
LEFT JOIN p_alerts as pa ON pm.id = pa.post_id AND pa.p_source_alert_id ='3849084'
group by pm.p_media_user_id;
The only thing that I am having issues with is the max(pm.timestamp), after the grouping I would expect it to show the NEWEST rows in the p_media table, but to the contrary it's doing the exact opposite and showing the oldest rows. So, I need the newest rows from the p_media table grouped by the user id which Join the p_users table.
Thanks in advance, if anyone helps.
As others have already pointed out, you are aggregating by the p_media_user_id column but then selecting other non aggregate columns. This either won't run at all, or it will run but give non determistic results. However, it looks like you just want the most recent record from the p_media table, for each p_media_user_id.
If so, then this would seem to be the query you intended to run:
SELECT
pm1.timestamp, pm1.id, pm1.p_media_user_id, pm1.p_media_type, pm1.p_media_file,
pm1.wall_post, pm1.p_media_location, pm1.p_media_location_name,
pm1.p_media_category, pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id,
pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image
FROM p_media as pm1
INNER JOIN
(
SELECT p_media_user_id, MAX(timestamp) AS max_timestamp
FROM p_media
GROUP BY p_media_user_id
) pm2
ON pm1.p_media_user_id = pm2.p_media_user_id AND
pm1.timestamp = pm2.max_timestamp
INNER JOIN p_users AS pu
ON pm1.p_media_user_id = pu.fb_id
LEFT JOIN p_alerts AS pa
ON pm1.id = pa.post_id AND
pa.p_source_alert_id = '3849084';
Your query is not doing what you think it is doing. When you use GROUP BY, only the columns that appear in the GROUP BY clause can be used in the SELECT without an aggregate function. All columns that are not in the GROUP BY clause MUST be using in an aggregate function when adding them to the SELECT.
This is the standard, and for all databases that follow the standards, you will get an error from your query. For some reason, MySQL decided not to follow the standards on this and no error is returned. This is really bad, because your query will run, but the results cannot be predicted. So you will think that the query is fine and will wonder why you get the wrong results, while in fact your query is invalid.
MySQL has finally addressed the problem and starting with MySQL 5.7.5, the ONLY_FULL_GROUP_BY SQL mode is enabled by default. The reason they gave is rather silly: because GROUP BY processing has become more sophisticated to include detection of functional dependencies., but at least they've changed the default and starting with MySQL 5.7.5, it will behave like most other databases. For earlier versions, if you have access to change the settings, I recommend enabling ONLY_FULL_GROUP_BY so you get a clear error for such invalid queries.
In some cases, you really don't care about the value returned for the non-aggregate columns, if all the values are exactly the same. To let the query pass while ONLY_FULL_GROUP_BY is enabled, use the ANY_VALUE() function on those columns. The is a better approach as it clearly indicate your intention.
To learn how you can fix your query, you can read How do we select non-aggregate columns in a query with a GROUP BY clause. You need to self-join the p_media table with only the p_media_user_id and MAX(timestamp) selected on the grouping:
SELECT pm.timestamp, pm.id, pm.p_media_user_id, pm.p_media_type, pm.p_media_file,
pm.wall_post, pm.p_media_location, pm.p_media_location_name, pm.p_media_category,
pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id,
pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image
FROM p_media as pm
INNER JOIN (SELECT p_media_user_id, MAX(timestamp) AS max_time
FROM p_media
GROUP BY p_media_user_id
) pmm ON pm.p_media_user_id = pmm.p_media_user_id
AND pm.timestamp = pmm.max_time
INNER JOIN p_users AS pu ON pm.p_media_user_id = pu.fb_id
LEFT JOIN p_alerts AS pa ON pm.id = pa.post_id
AND pa.p_source_alert_id = '3849084';
You should be able to add an ORDER BY after the grouping and tell SQL what column you want to sort by [ASC or DESC].
SELECT max(pm.timestamp), pm.id, pm.p_media_user_id, pm.p_media_type,
pm.p_media_file, pm.wall_post, pm.p_media_location,pm.p_media_location_name,
pm.p_media_category, pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id,
pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image
FROM p_media as pm
INNER JOIN p_users as pu ON pm.p_media_user_id = pu.fb_id
LEFT JOIN p_alerts as pa ON pm.id = pa.post_id AND pa.p_source_alert_id ='3849084'
group by pm.p_media_user_id
ORDER BY pm.p_media_user_id DESC;
I got this, and I want to get their "company" names for each one.
SELECT `client`.`name`,`client`.`lastname`
FROM `check`,`reserv`,`client`
WHERE `check`.`idReserv`=`reserv`.`id`
AND `reserv`.`idPerson`=`client`.`id`
ORDER BY `check`.`id`
, and I want to get their "company" names for each one, from table "company".
So I tried this:
SELECT `client`.`name`,`client`.`lastname`, `company`.`name`
FROM `check`,`reserv`,`client`,`company`
WHERE `reserv`.`idCompany`=`company`.`id`
AND `check`.`idReserv`=`reserv`.`id`
AND `reserv`.`idPerson`=`client`.`id`
ORDER BY `check`.`id`
but there is some people in the table "reserv" with an "idCompany" inexistent. so with that condition, this query only show me people who has an existent "id" in the table "company". I want to show the people with no company up and the space of company.name in blank if there is no company
I tryed many ways even with joins, but I cannot fix it. I'm tired to write "company" also.
You can use LEFT JOIN for this purpose like-
reserv r LEFT JOIN company c ON r.idCompany = c.id
You should use LEFT join instead.
SQL LEFT JOIN
SELECT c.name, c.lastname, co.name
FROM check AS ck
LEFT JOIN reserv AS r ON(ck.idReserv = r.id)
LEFT JOIN client AS c ON(r.idPerson = c.id)
LEFT JOIN company AS co ON(r.idCompany = co.id)
ORDER BY c.id
The ANSI 89 standard uses , notation for table joins with the criteria of the join being in the where clause. However I don't believe mySQL supports this outer style of join needed to address your problem. To express an outer join in this syntax you would need to use a *= for left join or =* for a right join; but again not sure mySQL supports it.
So in your case:
SELECT `client`.`name`,`client`.`lastname`, `company`.`name`
FROM `check`,`reserv`,`client`,`company`
WHERE `reserv`.`idCompany`*=`company`.`id`
AND `check`.`idReserv`=`reserv`.`id`
AND `reserv`.`idPerson`=`client`.`id`
ORDER BY `check`.`id`
However, I find that notation difficult to read and no need for all the escaping of table/column names (except reserved words)... so the below follows the ANSI 92 standards which allow for the use of INNER and LEFT Join syntax to explicitly define the type of join. Both notations should optimize to the same execution plan so either works (provided mySQL supports the *= notation) as well; it's just a matter of which standard you choose to use.
SELECT client.name
, client.lastname
, company.name
FROM `check`
INNER JOIN reserv
on `check`.idReserv=reserv.id
INNER JOIN client
on reserv.idPerson=client.id
LEFT JOIN company
on reserv.idCompany=company.id
ORDER BY `check`.id