IF ELSE or CASE in MySQL statement? - mysql

This is my MySQL Statement :
select
tableG.id,
TestName,
test_group.Merged as TestGroupMerged,
TestSuiteName,
test_suite.Merged as TestSuiteMerged,
test_case.Deleted as TestCaseDeleted,
Long_image_name as Image,
from
test_table
-- new added line -- inner join Long_image_name on test_B.long_image_id = image_table.long_image_id
inner join Long_image_name on test_A.long_image_id = image_table.long_image_id
where
db_test_id = ?
We are adding the image to another table(test_B) if test_B doesn't contain the image it should look in test_A if test_A also doesn't have it then blank image(nothing).
I am thinking to solve it like this:
IF (test_B.long_image_id IS NULL) THEN
inner join Long_image_name on test_A.long_image_id = image_table.long_image_id
ELSE
inner join Long_image_name on test_B.long_image_id = image_table.long_image_id
I cannot test the implementation yet because the database doesn't have any image files currently. Would using ´CASE´ be a better idea?
Thanks for your time!

You can't make conditional joins like that, but you could do the IF() test at a higher level:
SELECT COALESCE(test_B.long_image_id, test_A.long_image_id)
FROM ...
INNER JOIN ... test_A ...
INNER JOIN ... test_B ...

since you are testing for NULL and joining on IDs im assuming the image would only be in 1 of the 2 tables, which means the two INNER JOIN in the answer by Marc B should be changed to LEFT JOIN
SELECT COALESCE(test_B.long_image_id, test_A.long_image_id)
FROM ...
LEFT JOIN ... test_A ...
LEFT JOIN ... test_B ...

Or....
You should be able to do the following:
select *
from test_table test
inner join Long_image_name image on
(test.long_image_id IS NULL and test_A.long_image_id = image.long_image_id) or
(test.long_image_id IS NOT NULL and test_B.long_image_id = image.long_image_id)
Haven't fully tested it on my end, but it's worth a shot.
Side note, your joins don't look quite right, from my quick glance. Make sure you're joining between both tables right, either by alias or actual table name. You'll have to fix the references in the suggested join based on the same concept.
Side note: I've answered this from the mindset of SQL Server 2000, but should still point you the right way.

Related

Query returning data about nested elements

I have three tables in my database:
boards: idBoard, nameBoard, author
sections: idSection, nameSection, idBoard
tasks: idTask, nameTask, idSection
My query looks like this:
SELECT tasks.idTask, sections.idSection, (more...)
FROM `tasks`
INNER JOIN `boards` ON tasks.idBoard = boards.idBoard
INNER JOIN `sections` ON sections.idSection = tasks.idSection
WHERE boards.idBoard = ?
AND boards.author= ?
The query works almost well, but it doesn't return sections that don't have their tasks items.
Unfortunately, I don't really know why it works like that. I would also like to get section items matching boards but not having tasks items
I think you want outer joins, which usually means left join. Based on the way you describe your tables, I would expect the query to look like this:
SELECT t.idTask, s.idSection, (more...)
FROM boards b LEFT JOIN
sections s
ON b.idBoard = s.idBoard
tasks t
ON s.idSection = t.idSection
WHERE b.idBoard = ? AND boards.author= ?
I think you made a mistake in your query. tasks table doesn't have a column called 'idBoard' in your post.
How about this?
SELECT tasks.idTask, sections.idSection, (more...)
FROM `tasks`
INNER JOIN `sections` ON sections.idSection = tasks.idSection
INNER JOIN `boards` ON sections.idBoard = boards.idBoard
WHERE boards.idBoard = ?
AND boards.author= ?
Could you explain more about what you want?

Issue in mysql query

I have 2 tables:
table 1:userdetails with fields:uid,mobile,name
table 2:accountdetails with fields:uid,savings,balance
Where uid is common and primary key in both tables.
Now Iam trying to get mobile,savings values from both tables where uid =1 how can we get.I tried below but didnt worked.
select mobile,savings
from userdetails,accountdetails
where userdetails.uid='1'AND
userdetails.uid = accountdetails.uid
Please can some one help
More modern version using the JOIN syntax:
SELECT
a.`mobile`,
b.`savings`
FROM `userdetails` a
JOIN `accountdetails` b
ON a.`uid` = b.`uid`
WHERE a.`uid` = 1
The query should probably look like this:
select ud.mobile, ad.savings
from userdetails ud left join
accountdetails ad
on ud.uid = ad.uid
where ud.uid = 1;
Notes:
Use proper, explicit JOIN syntax.
Use meaningful table aliases and qualify all columns names.
The left join keeps all rows, even if there is no match in the second table. That might be your problem.
I am assuming that uid is actually a number. Don't put numbers around numeric constants.
You could turn on your error display to show you exactly what line is causing the issue.
ini_set('display_errors', 1);
You can try this.
SELECT `ud`.`mobile`, `ad`.`savings`
FROM `userdetails` `ud`
INNER JOIN `accountdetails` `ad` ON `ud`.`uid` = `ad`.`uid`
WHERE `us`.`uid` = 1
Use join
select mobile,savings
from userdetails join accountdetails on userdetails.uid = accountdetails.uid
where userdetails.uid='1'

Select slugs from TABLE_A that are not already in TABLE_B MySQL

I have the following mySQL code written in PHP
SELECT * FROM $photos;
I then have some code which adds the photo slug to a database into table 2. The photos table can grow large, so I want the SELECT above to only SELECT photos where the photo hasn't already been added. There's no timestamp or anything to work from, i.e something like
SELECT * FROM $photos INNER JOIN $slugs WHERE $photos. 'slugs' <> $slugs . 'slugs'
Am I going in the right direction here, INNER join is a bit confusing
Here's how to do it using a LEFT JOIN, which tends to be much faster than the NOT IN:
SELECT * FROM $photos
LEFT JOIN $slugs ON $photos.slugs = $slugs.slugs
WHERE $slugs.slugs IS NULL;
Yes you are going in the right direction but I think you can better use a Left Join instead of using a where clause.
Try like this:-
SELECT * FROM $photos LEFT JOIN $slugs ON $photos.slugs = $slugs.slugs
WHERE $photos.slugs IS NULL;

Taking one column from MySQL joined tables

I have a query in MySQL and I am making a crystal report by using this.
Now inside the query i have a column called scan_mode and it is coming from gfi_transaction table. This scan_mode I am using in report to suppress some sections. But some times this value is coming null for some transaction ids.
So now I want to take this scan_mode as separate query so that it will work.
Can any one please help how I can modify the below query to take only scan_mode column.
SELECT
cc.cost_center_code AS cccde,
cc.name AS ccnme,gf.scan_mode,
cc.cost_center_id AS ccid,
site.name AS siteme,
crncy.currency_locale AS currency_locale,
cntry.language AS LANGUAGE,
cntry.country_name AS cntrynm,
crncy.decimal_digits AS rnd,
gf.transaction_no AS Serial_No,
brnd.name AS brand_name,
rsn.description AS reason,
gf.comment AS COMMENT,
ts.status_description AS STATUS,
DATE_FORMAT(gf.created_date,'%d/%m/%Y') AS created_date,
gf.created_by AS created_by,
IFNULL(gf.approval_no,'Not authorized') AS Trans_no,
gf.approved_date AS approval_dt,
gf.approved_by AS approved_by,gf.status AS status1,
IFNULL(loc.cost_center_code,cc.cost_center_code) AS cur_location,
gf.document_ref_no,gf.document_ref_type,
,DATE_FORMAT(document_ref_date1,'%d/%m/%Y')) AS invoice_no
FROM
gfi_transaction gf
INNER JOIN gfi_instruction gfn ON (gf.transaction_id=gfn.transaction_id)
INNER JOIN gfi_document_instruction doc ON (gf.ref_transaction_no = doc.document_instruction_id)
INNER JOIN reason rsn ON (gf.reason_id = rsn.reason_id)
INNER JOIN gfi_status ts ON (gf.status = ts.gfi_status_id)
INNER JOIN transaction_type tt ON (gf.transaction_type_id = tt.transaction_type_id)
INNER JOIN brand brnd ON(gf.brand_id=brnd.brand_id)
-- cc details
INNER JOIN cost_center cc ON (brnd.parent_brand = cc.brand_id OR gf.brand_id = cc.brand_id)
INNER JOIN site site ON(cc.site_id = site.site_id)
INNER JOIN country cntry ON (site.country_id = cntry.country_id)
INNER JOIN currency crncy ON (cntry.currency_id=crncy.currency_id)
LEFT OUTER JOIN alshaya_location_details loc ON
(gf.brand_id = loc.brand_id AND loc.cost_center_id = gf.cost_centre_id)
LEFT OUTER JOIN alshaya_location_details locto ON
(locto.cost_center_id = gf.from_cost_center_id)
WHERE
gf.transaction_id='{?TransID}'
AND rsn.transaction_type_id IN (10,11,14)
wow, that's a big query. I ran across a similar problem in a query i was building and found the if syntax to be a solution to my problem. This was also answered in this question: MYSQL SELECT WITHIN IF Statement
$psdb->query = "SELECT count, s.classid,
if (k.sic != k.siccode, k.siccode, s.siccode) as siccode,
if (k.sic != k.siccode, k.sicdesc, s.sicdesc) as sicdesc,
if (k.sic != k.siccode, k.sicslug, s.sicslug) as sicslug
FROM ...
It looks like scan_mode column comes from "gfi_transaction" table which seems to be primary table in your query. If you get null for this column then it means your table itself have NULL value for this column. Taking that separately in a query wont solve your problem. Try replacing null with a default value and handle it in code. You can add default value instead of NULL by using ifnull(scan_mode, 'default')

The left joins making query slow,is there any method to increase the speed of this query

select
b.entry_id,
b.assign_id,
a.profile_type,
a.profile_id,
a.profile_name,
a.profile_status,
b.entry_type,
b.assign_id,
c.chapter_name,
d.section_name,
h.group_name,
i.programme_name,
k.subjectprogramme_name,
j.masterprogramme_name,
l.developmentprogramme_name
from profile_master a
left join profile_assign b on (a.profile_id = b.profile_id)
left join chapter_master c
on (b.entry_id = c.chapter_id and b.entry_type='chapter')
left join section_master d
on (b.entry_id = d.section_id and b.entry_type='section')
left join group_master h
on (b.entry_id = h.group_id and b.entry_type='Group'
and h.year_id='".$this->year."')
left join programme_master i
on (b.entry_id = i.programme_id and b.entry_type='Programme'
and i.year_id='".$this->year."')
left join subjectprogramme_master k
on (b.entry_id = k.subjectprogramme_id and b.entry_type='subjectProgramme'
and k.year_id='".$this->year."')
left join masterprogramme_master j
on (b.entry_id = j.masterprogramme_id and b.entry_type='masterProgramme'
and j.year_id='".$this->year."')
left join developmentprogramme_master l
on (b.entry_id = l.developmentprogramme_id
and b.entry_type='developmentProgramme')
1) Get rid of where coditions from left join. Use WHERE clause for filtering
2) I guess UNION or 7 queries (by each entity separetely) will be much better in your case
This is a hard question to answer without having direct access to the database, so I'll try a general answer!
Use "explain" on this query to see if MySQL suggests some indexes. No doubt it'll suggest a few, because you're accessing a few columns several times, and oftentimes indexes will improve even the slowest OUTER JOIN
You're using lots of checks against $this->year, so that would suggest some composite indexes where e.g. the programme_id and the year_id are both in the same index
Of course, there are solutions that might depend on how you're using the output, e.g.:
If this query is run frequently enough to be a problem for users waiting for it, but infrequently enough for latency not to be an issue (e.g. it's ok to run it based on last night's data), you could run it overnight and cache the results.
You really only do a join when a condition is passed, I suggest doing subselects like so:
SELECT
b.entry_id,
b.assign_id,
a.profile_type,
a.profile_id,
a.profile_name,
a.profile_status,
b.entry_type,
b.assign_id,
CASE b.entry_type
WHEN 'chapter' THEN SELECT(c.chapter_name FROM c WHERE b.entry_id = c.chapter_id)
WHEN 'section' THEN SELECT(d.section_name FROM d WHERE b.entry_id = d.section_id)
WHEN ....
END as name
from profile_master a
left join profile_assign b on (a.profile_id = b.profile_id)
If you insist on having the output be the same, then you need to wrap this select in a outer select like so:
SELECT
entry_id, assign_id, ......
, CASE entry_type WHEN 'chapter' THEN name ELSE null END as chapter_name
, CASE entry_type WHEN 'section' THEN name ELSE null END as section_name
FROM
(select statement like above) sub