How to query multiple Left Join table when there exist null - mysql

I have 20 tables (list of subjects) that has the same table structure as below.
columns
|id|student_id|result_session|result_term|result_arm|result_class|result_level|1st_test|2nd_test|exam|result_total|result_grade|result_remark|
I then have another table result_summary as below:
|id|student_id|result_score|result_average|result_term|result_session|result_level|result_class|result_arm
Minimal Query
When I write my query like so:
SELECT t2.`1st_test` AS agric1, t2.`2nd_test` AS agric2, t2.exam AS agricExam3, t2.result_total AS agricTotal,
t2.result_grade AS agricGrade, t3.`1st_test` AS basicsci1, t3.`2nd_test` AS basicsci2, t3.exam AS basicsciExam,
t3.result_total AS basicsciTotal, t3.result_grade AS basicsciGrade t2.result_remark AS agricRemark, t3.result_remark AS basicSciRemark
FROM ((result_summary AS t1 LEFT JOIN
agricultural_science AS t2 ON t1.student_id = t2.student_id) LEFT JOIN
basic_science AS t3 ON t1.student_id = t3.student_id)
WHERE (t1.student_id = '#studentID' AND t1.result_term = '#term' AND t1.result_session = '#session' AND t1.result_level = '#level' AND t1.result_class = '#resultClass') AND
(t2.student_id = '#studentID' AND t2.result_term = '#term' AND t2.result_session = '#session' AND t2.result_level = '#level' AND t2.result_class = '#resultClass') AND
(t3.student_id = '#studentID' AND t3.result_term = '#term' AND t3.result_session = '#session' AND t3.result_level = '#level' AND t3.result_class = '#resultClass')
It does not return any row. Mind you, there are data matching the query data in table t1 and t2 but not in t3.
How can I write the query to get the desire result? Thanks in advance.

Defining t2 and t3 table's conditions in where clause turns your left joins into INNER JOIN.
The t2 and t3 table's conditions will need to be defined in ON instead of WHERE:
select t2.`1st_test` as agric1,
t2.`2nd_test` as agric2,
t2.exam as agricExam3,
t2.result_total as agricTotal,
t2.result_grade as agricGrade,
t3.`1st_test` as basicsci1,
t3.`2nd_test` as basicsci2,
t3.exam as basicsciExam,
t3.result_total as basicsciTotal,
t3.result_grade as basicsciGrade t2.result_remark as agricRemark,
t3.result_remark as basicSciRemark
from (
(
result_summary as t1 left join agricultural_science as t2 on t1.student_id = t2.student_id
) left join basic_science as t3 on t1.student_id = t3.student_id
and (
t3.student_id = '#studentID'
and t3.result_term = '#term'
and t3.result_session = '#session'
and t3.result_level = '#level'
and t3.result_class = '#resultClass'
)
and (
t2.student_id = '#studentID'
and t2.result_term = '#term'
and t2.result_session = '#session'
and t2.result_level = '#level'
and t2.result_class = '#resultClass'
)
)
where (
t1.student_id = '#studentID'
and t1.result_term = '#term'
and t1.result_session = '#session'
and t1.result_level = '#level'
and t1.result_class = '#resultClass'
);

Related

How to create SQL-Query to update data in tables?

I'm trying to update data in my table.
I have two tables, t1 and t2
T1
T2
I'm want to do, that if t1 have id_avito = null and all_usl_name = %usl_name1% and all_tel = %tel1%, and t2 have id != null, usl_name = %usl_name1% and tel = %tel1%
For example, t1 after execute query must to look like that
update people.t1, people.t2
set
id_avito = people.t2.id,
lnk_avito = people.t2.link,
all_price = people.t2.price,
all_date = people.t2.date,
all_adr = people.t2.adr,
all_usl_name = people.t2.usl_name
where id_avito != people.t2.id
and all_tel= people.t2.tel
and all_usl_type = people.t2.usl_type
I try to do like this, but it is not working
UPD
EXAMPLE: tables. Table before update, after update, and second table
Try with update join also you need to use like operator where you are searching with string
update people.t1 a
join people.t2 on id_avito != people.t2.id
and all_tel= people.t2.tel
and all_usl_type = people.t2.usl_type
set
id_avito = people.t2.id,
lnk_avito = people.t2.link,
all_price = people.t2.price,
all_date = people.t2.date,
all_adr = people.t2.adr,
all_usl_name = people.t2.usl_name
Please try this.
For SQL
UPDATE A
SET
A.id_avito = B.id,
A.lnk_avito = B.link,
A.all_price = B.price,
A.all_date = B.date,
A.all_adr = B.adr,
A.all_usl_name = B.usl_name
FROM
people.t1 A
INNER JOIN people.t2 B
ON A.id_avito != B.id
AND A.all_tel= B.tel
AND A.all_usl_type =B.usl_type
where ISNULL(A.id_avito,'') ='' and A.all_usl_name like '%usl_name1%' and A.all_tel like '%tel1%' and B.id is not null and B.usl_name like '%usl_name1%' and B.tel like '%tel1%'
FOR MYSQL
UPDATE people.t1 a
INNER JOIN people.t2 B
ON A.id_avito != B.id
AND A.all_tel= B.tel
AND A.all_usl_type =B.usl_type
SET
A.id_avito = B.id,
A.lnk_avito = B.link,
A.all_price = B.price,
A.all_date = B.date,
A.all_adr = B.adr,
A.all_usl_name = B.usl_name
where IFNULL(A.id_avito,'') = '' and A.all_usl_name like '%usl_name1%' and A.all_tel like '%tel1%' and IFNULL(B.id,0) <> 0 and B.usl_name like '%usl_name1%' and B.tel like '%tel1%'

alternative to nested select mysql

I am running a query at the moment, and I believe that that nest selected is creating a bottle neck, is there an alternative option that I could use?
This is my query,
SELECT post_id,
post_order,
post_parent,
post_recycle,
post_status,
post_ps_id,
post_v_id,
post_src,
post_sn_id,
post_qpc_id,
post_date_posted,
post_scheduled_local_datetime,
post_recycle_repeats,
post_recycle_expiry_date,
post_text,
post_v_title,
link_url,
link_preview_removed,
link_name,
link_description,
link_caption,
link_url_is_bitlink,
link_bitly_destination_url,
link_expanded_url,
link_initial_is_bitlink,
link_destination,
link_picture,
link_picture_size,
link_facebook_image,
link_facebook_title,
link_facebook_description,
link_facebook_caption,
link_twitter_card,
link_twitter_image,
link_twitter_title,
link_twitter_description,
pause_m_id,
qpca_evergreen_too_frequent,
sn_network,
qpc_name,
qpc_colour,
ps_m_id,
ps_filename,
ps_via,
ps_s3,
ps_width,
ps_height,
ps_gif,
video.*,
(
SELECT COUNT(*) FROM post post_inner
WHERE (post_inner.post_parent = post.post_parent)
AND post_inner.post_status = 'published'
)
AS total_repeats
FROM post
JOIN social_network ON sn_id = post_sn_id AND sn_status = 'active'
JOIN queue_post_cat ON qpc_id = post_qpc_id
LEFT JOIN queue_post_cat_account ON qpca_qpc_id = post_qpc_id AND qpca_sn_id = post_sn_id
LEFT JOIN link ON link_id = post_link_id
LEFT JOIN pause ON pause_m_id = qpc_m_id AND pause_qpc_id = post_qpc_id AND pause_sn_id = post_sn_id
LEFT JOIN photo_status ON ps_id = post_ps_id
LEFT JOIN video ON post_v_id = v_id AND v_transcoded = 1 LEFT JOIN facebook ON fb_db_id = sn_account_id AND sn_network = 'facebook'
WHERE post_status != 'now'
AND post_m_id = 1
AND qpca_sn_id IS NOT NULL
AND qpca_qpc_id IS NOT NULL
AND post_status = 'queue' AND (sn_network = 'facebook'
OR sn_network = 'instagram' OR sn_network = 'twitter')
AND qpc_m_id = 1 AND (fb_type IS NULL OR fb_type != 'profile') ORDER BY post_order ASC
I believe the bottle neck is happening here,
SELECT COUNT(*) FROM post post_inner
WHERE (post_inner.post_parent = post.post_parent)
AND post_inner.post_status = 'published'
which is select within the main select, is there something I could do that would run faster?
You can try with subquery:
select * from
(
SELECT post_id,
post_order,
post_parent,
post_recycle,
post_status,
post_ps_id,
post_v_id,
post_src,
post_sn_id,
post_qpc_id,
post_date_posted,
post_scheduled_local_datetime,
post_recycle_repeats,
post_recycle_expiry_date,
post_text,
post_v_title,
link_url,
link_preview_removed,
link_name,
link_description,
link_caption,
link_url_is_bitlink,
link_bitly_destination_url,
link_expanded_url,
link_initial_is_bitlink,
link_destination,
link_picture,
link_picture_size,
link_facebook_image,
link_facebook_title,
link_facebook_description,
link_facebook_caption,
link_twitter_card,
link_twitter_image,
link_twitter_title,
link_twitter_description,
pause_m_id,
qpca_evergreen_too_frequent,
sn_network,
qpc_name,
qpc_colour,
ps_m_id,
ps_filename,
ps_via,
ps_s3,
ps_width,
ps_height,
ps_gif,
video.*,
FROM post
JOIN social_network ON sn_id = post_sn_id AND sn_status = 'active'
JOIN queue_post_cat ON qpc_id = post_qpc_id
LEFT JOIN queue_post_cat_account ON qpca_qpc_id = post_qpc_id AND qpca_sn_id = post_sn_id
LEFT JOIN link ON link_id = post_link_id
LEFT JOIN pause ON pause_m_id = qpc_m_id AND pause_qpc_id = post_qpc_id AND pause_sn_id = post_sn_id
LEFT JOIN photo_status ON ps_id = post_ps_id
LEFT JOIN video ON post_v_id = v_id AND v_transcoded = 1 LEFT JOIN facebook ON fb_db_id = sn_account_id AND sn_network = 'facebook'
WHERE post_status != 'now'
AND post_m_id = 1
AND qpca_sn_id IS NOT NULL
AND qpca_qpc_id IS NOT NULL
AND post_status = 'queue' AND (sn_network = 'facebook'
OR sn_network = 'instagram' OR sn_network = 'twitter')
AND qpc_m_id = 1 AND (fb_type IS NULL OR fb_type != 'profile')) A
inner join
(
SELECT post_parent ,COUNT(*) FROM post where post_status = 'published' group by post_parent
) B on A.post_parent = B.post_parent
ORDER BY post_order ASC

Multiple rows in a select with OR

I have this query and when I add a OR, return multiples rows, how I can fix this? I need another left join or Right join?
SELECT `images`.`id` as `id_image`, `images_lang`.`title` as `title`, `images_lang`.`autor` as `author`, `media_lang`.`file`, `category_lang`.`title` as `category`
FROM `images`
JOIN `images_lang` ON `images_lang`.`id_images` = `images`.`id`
JOIN `category_lang` ON `images`.`id_category` = `category_lang`.`id_category`
JOIN `media` ON `images`.`id` = `media`.`id_item`
JOIN `media_lang` ON `media`.`id` = `media_lang`.`id_media`
JOIN `relation` ON `relation`.`from_id` = `images`.`id`
JOIN `tag` ON `tag`.`id` = `relation`.`to_id`
JOIN `tag_lang` ON `tag`.`id` = `tag_lang`.`id_lang`
WHERE `media`.`table` = 'images'
AND `media_lang`.`id_lang` = '1'
AND `images_lang`.`id_lang` = '1'
AND `category_lang`.`id_lang` = '1'
AND `images`.`active` = 1
AND `relation`.`type` = 2
AND `tag_lang`.`id_lang` = '1'
AND `tag_lang`.`slug` = 'pa-am-oli'
OR `tag_lang`.`slug` = 'playa'
LIMIT 9
and the code in codeigniter, but I donĀ“t how add the or after the and ($keywords is an array for filter the elements)
$this->db->select('images.id as id_image, images_lang.title as title, images_lang.autor as author, media_lang.file, category_lang.title as category');
$this->db->from($this->table);
$this->db->join($this->table.'_lang',$this->table.'_lang.id_images = '.$this->table.'.id');
$this->db->join('category_lang',$this->table.'.id_category = category_lang.id_category');
$this->db->join('media',$this->table.'.id = media.id_item');
$this->db->join('media_lang','media.id = media_lang.id_media');
$this->db->where('media.table',$this->table);
$this->db->where('media_lang.id_lang',$id_lang);
$this->db->where($this->table.'_lang.id_lang', $id_lang);
$this->db->where('category_lang.id_lang', $id_lang);
$this->db->where('images.active', 1);
if($category){
$this->db->where('category_lang.title', $category);
}
if($keywords){
$this->db->join('relation', 'relation.from_id = '.$this->table.'.id');
$this->db->join('tag', 'tag.id = relation.to_id');
$this->db->join('tag_lang', 'tag.id = tag_lang.id_lang');
$this->db->where('relation.type', _IMAGES_2_TAGS_);
$this->db->where('tag_lang.id_lang', $id_lang);
foreach($keywords as $tag){
$this->db->or_where('tag_lang.slug', $tag);
}
}
if($from || $limit)
{
$this->db->limit((int)$limit, (int)$from);
}
$query = $this->db->get();
return $query->result_array();
I solved the query adding this (and a Select Distinct)
AND (`tag_lang`.`slug` = 'playa'
OR `tag_lang`.`slug` = 'pa-am-oli')
How I can add this in codeigniter?
I don't get what you need exactly, but if you want have just one line as a return by filtering using OR
In your case you should do the following:
WHERE (`media`.`table` = 'images' OR `tag_lang`.`slug` = 'playa')
AND (`media_lang`.`id_lang` = '1' OR `tag_lang`.`slug` = 'playa')
and so on, I hope that helps you and good luck!
Astute use of parentheses would solve your problem, but this is easier to read...
SELECT i.id id_image
, il.title
, il.autor author
, ml.file
, cl.title category
FROM images i
JOIN images_lang il
ON il.id_images = i.id
JOIN category_lang cl
ON cl.id_category = i.id_category
JOIN media m
ON m.id_item = i.id
JOIN media_lang ml
ON ml.id_media = m.id
JOIN relation r
ON r.from_id = i.id
JOIN tag t
ON t.id = r.to_id
JOIN tag_lang tl
ON tl.id_lang = t.id
WHERE m.table = 'images'
AND ml.id_lang = 1
AND il.id_lang = 1
AND cl.id_lang = 1
AND i.active = 1
AND r.type = 2
AND tl.id_lang = 1
AND tl.slug IN('pa-am-oli','playa')
LIMIT 9
... however, note that LIMIT without ORDER BY is fairly meaningless.

Why MYSQL doesn't use my indexes?

I have table karton00 which holds thousands of records. This makes the queries slow. I would like to use indexes, but even though I set them, they are not being used.
Here is my table. and here is the result of using EXPLAIN.
This is my query:
SELECT '' checkbox,
k00_eszkozid,
k00_eszkoznev,
k01_gyariszam,
k01_leltszam,
prsn_name,
k00_status,
tstikon,
k00_startflow,
tstname,
k00_eszkozid,
k01_gyariszam,
k01_leltszam
FROM karton00
LEFT JOIN karton01
ON k00_eszkozid = k01_eszkozid
AND k01_status = 'A'
LEFT JOIN karton02
ON k00_eszkozid = k02_eszkozid
AND k02_status = 'A'
LEFT JOIN karton04
ON k00_eszkozid = k04_eszkozid
AND k04_status = 'A'
LEFT JOIN karton05
ON k00_eszkozid = k05_eszkozid
AND k05_status = 'A'
LEFT JOIN karton06
ON k00_eszkozid = k06_eszkozid
AND k06_status = 'A'
LEFT JOIN karton08
ON k00_eszkozid = k08_eszkozid
AND k08_status = 'A'
LEFT JOIN karton09
ON k00_eszkozid = k09_eszkozid
AND k09_status = 'A'
LEFT JOIN telephely et
ON k06_telephelyid = et.telepid
LEFT JOIN ktghely00 ek
ON k02_ktghid = ek.ktghid
LEFT JOIN person00 us
ON k06_userid = prsn_id
LEFT JOIN ktghely00 fk
ON prsn_ktgh = fk.ktghid
LEFT JOIN telephely ft
ON prsn_telep = ft.telepid
LEFT JOIN tamstatus
ON k02_tamstatusid = tstid
LEFT JOIN szakleltar
ON k02_szakleltarid = szleltid
LEFT JOIN tamszerv
ON k02_tamszervid = tszid
LEFT JOIN ktghely01
ON k02_vgazdaid = vgid
AND vgstatus = 'A'
LEFT JOIN ktghely00 vk
ON vgktghid = vk.ktghid
LEFT JOIN szallitok m
ON k05_mincegid = m.szallid
LEFT JOIN szallitok s
ON k04_szallitoid = s.szallid
LEFT JOIN dctnry00 ym
ON k05_minosit = ym.dctnryname
AND ym.dctnrygrp = 'YESNO'
LEFT JOIN dctnry00 yd
ON k05_check = yd.dctnryname
AND yd.dctnrygrp = 'YESNO'
WHERE k00_status IN ( 'A', 'H' )
AND ( k02_vgazdaid IN ( 7 ) )
AND NOT EXISTS (SELECT *
FROM eszkozkizar
WHERE ez_flid = 0
AND ez_emintaid = k00_eszkozmintaid
AND k00_uzembedatum < ( Date_add(Curdate(),
INTERVAL ez_honap month) )
AND k00_uzembedatum != ''
AND k02_vgazdaid NOT IN ( 7 ))
AND NOT EXISTS(SELECT *
FROM eszkozkizar
WHERE ez_flid = 0
AND ez_emintaid = k00_eszkozmintaid
AND k02_tamszervid = ez_tamszerv
AND k02_tamstatusid = ez_tamsts
AND k00_uzembedatum < ( Date_add(Curdate(),
INTERVAL ez_honap month) )
AND k00_uzembedatum != ''
AND k02_vgazdaid NOT IN ( 7 ))
ORDER BY k00_eszkoznev ASC;
Also you can use USE INDEX (index_list) statement: http://dev.mysql.com/doc/refman/5.5/en/index-hints.html

Mysql update using values from select

I have two queries. The first will return multiple rows:
SELECT parent_entry_id,child_entry_id FROM exp_playa_relationships WHERE parent_field_id = '34';
...And I would like to use the values (parent_entry_id,child_entry_id) and incorporate them into this query, replacing 'x' and 'y', and do it for each row returned by the first query.
UPDATE exp_channel_data AS t1,
(
SELECT field_id_46,field_id_47 FROM exp_channel_data WHERE entry_id = 'x') AS t2
SET t1.field_id_60 = t2.field_id_46, t1.field_id_61 = t2.field_id_47
WHERE t1.entry_id = 'y';
I think I need to use another JOIN, but I can't figure out how to implement one in my example. Any help would be much appreciated.
I think this is what you're after:
UPDATE exp_playa_relationships AS t0
JOIN exp_channel_data AS t1
ON t1.entry_id = t0.child_entry_id
JOIN exp_channel_data AS t2
ON t2.entry_id = t0.parent_entry_id
SET t1.field_id_60 = t2.field_id_46
, t1.field_id_61 = t2.field_id_47
Try this query
UPDATE exp_channel_data a1 INNER JOIN exp_playa_relationships a ON a1.entry_id = a.child_entry_id
INNER JOIN exp_channel_data b ON a.parent_entry_id = b.entri_id
SET a1.field_id_60 = b.field_id_46, ta1.field_id_61 = b.field_id_47
WHERE parent_field_id = '34'
Thanks all for your replies. The working syntax is:
UPDATE exp_channel_data AS t1,
(
SELECT
entry_id as ei2, child_entry_id, parent_entry_id, field_id_46 as f46,field_id_47 as f47
FROM
exp_channel_data JOIN exp_playa_relationships ON entry_id=child_entry_id AND parent_field_id = 34) AS t2
SET t1.field_id_60 = f46, t1.field_id_61 = f47
WHERE t1.entry_id=parent_entry_id;
Or in a more classic syntax, you need to adjust to your own foo & bar attributes, but use something like the following:
update exp_channel_data t1
set (t1.field_id_60,t1.field_id_61) = (
select t2.field_id_46 , t2.field_id_47
from exp_channel_data t2
where 1=1
and t2.entry_id = 'x'
and /* ENTER YOUR t1-t2 join condition here */
)
where 1=1
and t1.entry_id = y
;
But since you are MySQL I don't believe it supports compound subquery. As such:
update exp_channel_data t1
set t1.field_id_60 = (
select t2.field_id_46
from exp_channel_data t2
where 1=1
and t2.entry_id = 'x'
and /* ENTER YOUR t1-t2 join condition here */
) , t1.field_id_61 = (
select t3.field_id_47
from exp_channel_data t3
where 1=1
and t3.entry_id = 'x'
and /* ENTER YOUR t1-t3 join condition here */
)
where 1=1
and t1.entry_id = y
;