Update rows from multiple tables and - mysql

I am working on a project where I need to update 2 tables in a query.
I am doing this
UPDATE ward_beds a, ipd_patient_list b
SET
a.occupation_status = 'empty',
b.patient_status = 'Discharged'
WHERE
a.ward_id = b.ward_id AND b.patient_id = '4'
AND
b.appointment_id = '6' AND b.ward_id = '1'
so far it is working, now I want to update this
b.patient_status = 'Discharged'
on the row which is the last in all matching rows. I tried to put this
ORDER BY b.row_id DESC LIMIT 1
but it shows
#1221 - Incorrect usage of UPDATE and ORDER BY
error. How should I do it?

You can't use limit in this kind of update
but you could seach for the correct id using a subquery and join to the others tables
UPDATE ward_beds a
INNER JOIN (
select ward_id, max(row_id) last_id
from ipd_patient_list
group by ward_id
) t on t.ward_id = a.ward_id
INNER JOIN ipd_patient_list b ON a.ward_id = b.ward_id
AND b.patient_id = '4'
AND b.appointment_id = '6'
AND b.ward_id = '1'
AND b.row_id = t.last_id
SET a.occupation_status = 'empty',
b.patient_status = 'Discharged'

Related

SELECT Statement should return 0 when condition is not met

How can I make following MYSQL statment return 0 in case that the condition is not met.
(SELECT Sum(B.trblksize) AS RxData
FROM referencecoexistence_ber_lte B,
(SELECT C.*
FROM referencecoexistence C
WHERE `sw_ver` = '0.4'
AND `lte_n_frames` = '50'
AND `lte_rb` = '6'
AND `lte_mcs` = '11'
AND `lte_p_mw` = '6.000000e-03'
AND `lte_vmsf_type` = 'BS'
AND `lte_vmsf_subframes` = '8 9'
AND `wlan_mcs` = '5'
AND `wlan_p_mw` = '100'
AND `channel` = 'A330'
AND `lte_freq_hz` = '2403000000'
AND `wlan_freq_hz` = '2412000000'
AND `wlan_ieee` = '802.11n') AS TableX
WHERE TableX.id = B.id
AND B.ber = '0'
GROUP BY lte_dist_m)
The result is: Empty set (0.280 sec)
If the condition includes B.ber = '0' the expected output is:
A result with b.ber = 0 looks like:
RxData
416342016
433004544
...
In my case it would be sufficient if it simply returns one entry:
RxData
0
This statement is embedded in a larger statement that calculates some throughput.
Is it possible without executing the statement twice?
Here we'll change this to a LEFT OUTER JOIN. We will move the B.ber = '0' condition into the FROM clause, because with an outer join, this will give us different results than if the condition is in the WHERE clause.
SELECT Sum(B.trblksize) AS RxData
FROM (SELECT C.*
FROM referencecoexistence C
WHERE `sw_ver` = '0.4'
AND `lte_n_frames` = '50'
AND `lte_rb` = '6'
AND `lte_mcs` = '11'
AND `lte_p_mw` = '6.000000e-03'
AND `lte_vmsf_type` = 'BS'
AND `lte_vmsf_subframes` = '8 9'
AND `wlan_mcs` = '5'
AND `wlan_p_mw` = '100'
AND `channel` = 'A330'
AND `lte_freq_hz` = '2403000000'
AND `wlan_freq_hz` = '2412000000'
AND `wlan_ieee` = '802.11n') AS TableX
LEFT OUTER JOIN referencecoexistence_ber_lte B
ON TableX.id = B.id
AND B.ber = '0'
GROUP BY lte_dist_m
Now when B.ber is zero, it will act like an inner join. However, when B.ber is not zero, then the inner join result will be missing from the join, but the outer join will include the result with all the columns of the B table, but NULL for all the columns of the TableX table. So those records will have B.trblksize as NULL, and their sum will be NULL.
I solved the problem by simply using following approach
(SELECT SUM(IF(T_.BER =0,T_.TrBlkSize,0)) as RxData, Lte_Dist_m FROM
(ReferenceCoexistence WHERE <CONDITION LIST>) as X,
ReferenceCoexistence_BER_Lte as T_
WHERE X.ID = T_.ID GROUP BY Lte_Dist_m)

MySQL QUERY runs on localhost, but does not on server

I have this QUERY:
select
a.*
from
mt_proyecto a,
mt_mockup b,
mt_diseno c,
mt_modulo d
where
a.estado = 'A' and
(
(b.encargado = '1' and b.idproyecto = a.idmtproyecto) or
(c.encargado = '1' and c.idproyecto = a.idmtproyecto) or
(d.encargado = '1' and d.idproyecto = a.idmtproyecto)
)
group by
a.idmtproyecto
order by a.finalizado asc, a.feccrea desc
Result:
Then, I run the same code on server with the same database:
Is there any problem with the query?
It seems that the query is running correctly on your server, and returning no rows. Please make sure you have the same table contents on your local machine and your server.
Other things:
Pro tip: never use SELECT * or SELECT table.* in software. Always enumerate the columns you want in your result set.
Unless you use GROUP BY with aggregate functions like SUM() or `COUNT(), and naming the correct columns from the result set, it returns unpredictable results. Read this. http://dev.mysql.com/doc/refman/5.1/en/group-by-extensions.html
I solved with this QUERY:
select
a.*
from
(
mt_proyecto a
left join mt_mockup b on
b.idproyecto = a.idmtproyecto
left join mt_diseno c on
c.idproyecto = a.idmtproyecto
left join mt_modulo d on
d.idproyecto = a.idmtproyecto
left join mt_integracion e on
e.idproyecto = a.idmtproyecto
left join mt_pruebas_internas f on
f.idproyecto = a.idmtproyecto
)
where
a.estado = 'A' and
(
(a.idmtproyecto = b.idproyecto and
b.encargado = '1' ) or
(a.idmtproyecto = c.idproyecto and
c.encargado = '1' ) or
(a.idmtproyecto = d.idproyecto and
d.encargado = '1' ) or
(a.idmtproyecto = e.idproyecto and
e.encargado = '1' ) or
(a.idmtproyecto = f.idproyecto =
f.encargado = '1' )
)
group by a.idmtproyecto
order by
a.finalizado asc, a.feccrea desc
Thanks everyone for answer me. I'll do your suggestions .

MySQL: How to optimize this query?

I almost spent a day to optimize this query:
SELECT
prod. *,
cat.slug category_slug,
sup.bname bname,
sup.slug bname_slug
FROM bb_admin.bb_directory_products AS prod
LEFT JOIN bb_admin.bb_categories_products AS cat
ON prod.primary_category_id = cat.category_id
LEFT JOIN bb_admin.bb_directory_suppliers AS sup
ON prod.supplier_id = sup.supplier_id
LEFT JOIN bb_admin.bb_directory_suppliers AS credit_sup
ON prod.credit_supplier_id = credit_sup.supplier_id
LEFT JOIN bb_admin.bb_directory_suppliers AS photo_sup
ON prod.photo_supplier_id = photo_sup.supplier_id
WHERE (
prod.status = '1'
OR prod.status = '3'
OR prod.status = '5'
)
AND (
sup.active_package_id != '1'
OR sup.active_package_id != '5'
OR sup.active_package_id != '6'
OR prod.supplier_id = '0'
)
AND (
sup.supplier_id = '1989'
OR credit_sup.supplier_id = '1989'
OR photo_sup.supplier_id = '1989'
)
GROUP BY prod.product_id
ORDER BY prod.priority_index ASC
Can you help me to optimized this query?
Update your column data types to be INT or one of its variants, since the ones you are checking against are all integer IDs (assumption).
Create indexes on following columns(if possible in all tables):
prod.status
supplier_id
active_package_id
Use IN clause instead of concatenating OR segments.
I'll be putting the updated WHERE clause here:
WHERE prod.status IN(1, 3, 5)
AND ( sup.active_package_id NOT IN(1, 5, 6)
OR prod.supplier_id = 0
)
AND 1989 IN (prod.supplier_id, prod.credit_supplier_id, prod.photo_supplier_id)

mysql join with multiple conditions (not OR but AND)

i have problem with join table and use multiple conditions...
My code:
SELECT * FROM
(SELECT sid, MAX(info_date_add) AS max_info_date_add FROM skiresort GROUP BY sid) skiresort_max
INNER JOIN skiresort
ON
skiresort_max.sid = skiresort.sid AND
skiresort_max.max_info_date_add = skiresort.info_date_add
JOIN skiresort_theme_value
ON skiresort_theme_value.skiresort_id = skiresort.id
WHERE
skiresort_theme_value.skiresort_theme_id = '1' AND
skiresort_theme_value.skiresort_theme_id = '2' AND
skiresort_theme_value.skiresort_theme_id = '4'
GROUP BY skiresort.sid
ORDER BY skiresort.title_en
In this code, the conditions are in WHERE clausule. I also tried to put in into JOIN ON (...) but it also didn't work.
When i have only one condition it works. I read some articles about using OR instead of AND, it worked but not as i expected. I need to search only rows with certain IDs (multiple).
why not use this instead of many conditions.
WHERE
skiresort_theme_value.skiresort_theme_id in (1, 2,4)
GROUP BY skiresort.sid
HAVING COUNT(DISTINCT skiresort_theme_value.skiresort_theme_id) = 3
ORDER BY skiresort.title_en
when add condition to WHERE, condition must be from FROM tbl
add condition JOIN ON
Try this:
SELECT * FROM
(SELECT sid, MAX(info_date_add) AS max_info_date_add FROM skiresort GROUP BY sid) skiresort_max
INNER JOIN skiresort
ON
skiresort_max.sid = skiresort.sid AND
skiresort_max.max_info_date_add = skiresort.info_date_add
JOIN skiresort_theme_value
ON (skiresort_theme_value.skiresort_id = skiresort.id AND skiresort_theme_value.skiresort_theme_id = '1' AND skiresort_theme_value.skiresort_theme_id = '2' AND skiresort_theme_value.skiresort_theme_id = '4')
GROUP BY skiresort.sid
ORDER BY skiresort.title_en

Combine conditions with AND in Mysql ON clause

I have the following query, that I use to filter rows based on software_id and level.
I've put the conditions in the ON-Clause since I still want rows returned, where there are no corresponding rows in the JobadvertsSoftware Table.
SELECT `Jobadvert`.`id` FROM `jobadverts` AS `Jobadvert`
LEFT JOIN `users` AS `User` ON (`Jobadvert`.`user_id` = `User`.`id`)
LEFT JOIN `jobadverts_softwares` AS `JobadvertsSoftware_0` ON
(`Jobadvert`.`id` = 'JobadvertsSoftware_0.jobadvert_id' AND
(`JobadvertsSoftware_0`.`software_id` = '32' AND
`JobadvertsSoftware_0`.`level` IN ('1', 4)))
WHERE `Jobadvert`.`active` = 1 AND `User`.`premium` = '1' AND
Jobadvert`.`department_id` = (5)
GROUP BY `Jobadvert`.`id`
The problem is that it also returns JobadvertsSoftware-rows where level is e.g. 2
Again, if I put that in the WHERE clause it will filter out the rows where there are not JobadvertsSoftware which it shouldn't do.
How can I tell MySQL to return all rows of Jobadvert, where the given software_id AND the level matches or are NULL?
Try this:
SELECT `Jobadvert`.`id`, `JobadvertsSoftware_0`.`level`
FROM `jobadverts` AS `Jobadvert`
LEFT JOIN `users` AS `User` ON (`Jobadvert`.`user_id` = `User`.`id`)
INNER JOIN `jobadverts_softwares` AS `JobadvertsSoftware_0` ON
(`Jobadvert`.`id` = 'JobadvertsSoftware_0.jobadvert_id' AND
(`JobadvertsSoftware_0`.`software_id` = '32' AND
`JobadvertsSoftware_0`.`level` IN ('1', 4)))
WHERE `Jobadvert`.`active` = 1 AND `User`.`premium` = '1' AND
Jobadvert`.`department_id` = (5)
GROUP BY `Jobadvert`.`id`
Saludos!
Try this( it's a bit unclear if some fields are numeric on string, it might be corrected):
SELECT distinct(`Jobadvert`.`id`) FROM `jobadverts` AS `Jobadvert`
LEFT JOIN `users` AS `User` ON (`Jobadvert`.`user_id` = `User`.`id`)
LEFT JOIN `jobadverts_softwares` AS `JobadvertsSoftware_0`
ON `Jobadvert`.`id` = `JobadvertsSoftware_0.jobadvert_id`
WHERE
`Jobadvert`.`active` = 1
AND `User`.`premium` = '1'
AND Jobadvert`.`department_id` = (5)
AND JobadvertsSoftware_0`.`software_id` = '32'
AND (`JobadvertsSoftware_0`.`level` IN (1, 4) OR `JobadvertsSoftware_0`.`level` is NULL)
Assuming the level parameters in your ON clause is not needed for the join you can do a nested SELECT on your Software table to clear out the data you do not need first:
SELECT * FROM jobadverts_softwares
WHERE
(`software_id` = 32 OR `software_id` IS NULL) --Select all software_id that are 32 or null
AND
`level` IN (1, 4)
Then you can incorporate this as a nested statement in your main SQL query so you only join on the data which is filtered in your LEFT JOIN but keep any null values that you needed:
SELECT `Jobadvert`.`id`
FROM `jobadverts` AS `Jobadvert`
LEFT JOIN `users` AS `User`
ON `Jobadvert`.`user_id` = `User`.`id`
LEFT JOIN
( --Software Subquery
SELECT `jobadvert_id`, `level` FROM jobadverts_softwares
WHERE
(`software_id` = 32 OR `software_id` IS NULL) --Select all software_id that are 32 or null
AND
`level` IN (1, 4)
) AS `software_subquery`
ON `Jobadvert`.`id` = `software_subquery`.`jobadvert_id`
WHERE
`Jobadvert`.`active` = 1
AND
`User`.`premium` = '1'
AND
`Jobadvert`.`department_id` = 5
ORDER BY `Jobadvert`.`id` --Changed GROUP BY to ORDER BY as not needed
This is untested but try it out and see if this will help.
Try this:
SELECT j.id
FROM jobadverts j
LEFT JOIN User u ON (j.user_id = u.id)
LEFT JOIN jobadverts_softwares AS js ON
(j.id = js.jobadvert_id)
WHERE j.active = 1
AND u.premium = '1'
AND j.department_id = (5)
AND js.software_id` = '32'
AND js.level IN ('1', 4)))
You won't need a GROUP BY unless summing data in some way.