mysql syntax for IFNULL with subquery - mysql

I want to use subquery inside of IFNULL statement
SELECT t.col1
, IFNULL(t.col2, (SELECT an.col_11
FROM another_table an
WHERE an.col1 = t.col5)) as alias_name
, t.col3
FROM table t;
In IFNULL statement second expression should be subquery.
Please give me proper syntax
My actual query is
SELECT u.username, up.gender, d.name, desg.name,
IFNULL(up.creative_lead_id,
(SELECT au.username FROM auth_user au
WHERE au.id=up.creative_lead_id)) as creative_lead, up.image
FROM user_profile up, department d, designation, auth_user
WHERE up.department_id=d.id
AND up.designation_id = desg.id up.auth_uesr_id = u.id;
This query is giving syntax error because of IFNULL statement.

You can rewrite your query with join,Correlated query will execute for each row in your table and it might affect the performance
SELECT
t.col1,
IFNULL(t.col2, an.col_11) AS alias_name,
t.col3
FROM
`table` t
LEFT JOIN another_table an
ON an.col1 = t.col5

Don't use a subquery for this situation, try a query like that instead (use of jointure):
SELECT t.col1
,IFNULL(t.col2, an.col_11) AS alias_name
,t.col3
FROM your_table t
LEFT JOIN another_table an ON an.col1 = t.col5
In your full query, your using twice up.creative_lead_id for your IFNULL clause (once as first parameter and then in the subquery). That make no sense because if the first param is NULL, your subquery will return no result!
In order to show you the principe that will solve your problem, i just replaced the first param by a fictive one that i called up.creative_lead. This fictive column is the name of the creative lead stored in your table user_profile and if this value is null, i'm looking to the username of the user corresponding to creative_lead_id.
Here is the full query that'll solve your problem with the correction mentioned above:
SELECT u.username
,up.gender
,d.name
,desg.name
,IFNULL(up.creative_lead, cl.username) AS creative_lead
,up.image
FROM user_profile up
INNER JOIN department d ON d.id = up.department_id
INNER JOIN designation desg ON desg.id = up.designation_id
INNER JOIN auth_user u ON u.id = up.auth_user_id
INNER JOIN auth_user cl ON cl.id = up.creative_lead_id
Notice that i changed the syntax of your query, it's highly recommended to avoid the use of old syntax for jointures (use explicit JOIN clause instead).
Hope this will help you.

Related

SQL - Passing column in subquery

my command:
Select sobe.Id, sobe.Naziv, sobe.Opis, sobe.Kat, (Select Group_CONCAT(studenti.Ime,studenti.Prezime) ImePrezime FROM studentsoba LEFT JOIN studenti ON studentsoba.Id_Sobe=sobe.Id AND studenti.JMBAG = studentsoba.JMBAG) AS ImePrezime from Sobe
This gives me this error:
1054 - Unknown column 'sobe.Id' in 'on clause'
I see what the problem is but I cant figure out how to fix it.
I want to pass sobe.Id inside of this subquery:
(Select Group_CONCAT(studenti.Ime,studenti.Prezime) ImePrezime FROM studentsoba LEFT JOIN studenti ON studentsoba.Id_Sobe=sobe.Id AND studenti.JMBAG = studentsoba.JMBAG)
I want to check which students are in that room.
Word soba means room and JMBAG is like personal number for each student
Try moving it to a WHERE clause:
Select s.Id, sobe.Naziv, s.Opis, s.Kat,
(Select Group_CONCAT(si.Ime, si.Prezime) as ImePrezime
from studentsoba ss LEFT JOIN
studenti si
on si.JMBAG = ss.JMBAG
where ss.Id_Sobe = s.Id
) AS ImePrezime
from Sobe s;
The correlated subquery should be fine. I suppose the correlation clause cannot be in the on clause -- I normally put it in the where clause anyway.
Also note that I introduced table aliases so the query is easier to write and to read.

Redshift - SQL Left Join does not work with correlated subquery and aggregated function

I am quite new to Redshift SQL and have been trying to figure out what's wrong with my syntax.
My task is to join 2 tables: question and user via left join as I want to retain all values from table question.
At the moment it throws the following error message: [Amazon](500310) Invalid operation: This type of correlated subquery pattern is not supported yet; when I use left join. On the other hand, when I change the code to join it works just fine. I suspect this is because I have an aggregated function and logical expression within my subquery that makes my left join an inner join.
But as I mentioned above, I need to retain all values from table question.
Below is my code
select
qa.user_id as user_email,
i.timestamp as session_login_time,
qa.timestamp as question_ask_time,
qa.question_id,
qa.question
from
schema1.question as qa
left join
schema1.user as i
on
qa.user_id = i.email
and
i.timestamp =
(select
max(timestamp)
from schema1.user
where
timestamp <= qa.timestamp)
where user_email <> 'tester' and user_email not like '%tester.com'
group by qa.user_id, i.timestamp, qa.timestamp, qa.question_id, qa.question
The purpose of the subquery is to get the closest session_login_time to each of the question_ask_time. So, multiple rows of question can have the same session_login_time value.
Could anybody please help me identify what I am missing from my code above? How do I make my left join works?
Thank you so much!
I guess that should get you the same results without involving a sub query
select
qa.user_id as user_email,
max(i.timestamp) as session_login_time,
qa.timestamp as question_ask_time,
qa.question_id,
qa.question
from schema1.question as qa
left join schema1.user as i
on qa.user_id = i.email
and i.timestamp <= qa.timestamp
where qa.user_id <> 'tester' and qa.user_id not like '%tester.com'
group by qa.user_id, qa.timestamp, qa.question_id, qa.question

subquery is not working in mysql

This is my mysql query
SELECT tm.MAGAZINE_ID, tm.MAGAZINE_NAME,tm.MAGAZINE_DESCRIPTION,pub.publisher_name,
tmi.COVER_PAGE_THUMB AS COVER_PAGE_VERTICAL,tmi.FROM_DATE AS ISSUE_DATE,
tm.html_flag AS HTML_EXIST,tm.CATEGORY_ID,tm.language_id,tm.is_free,tma.AppUrl,
(SELECT issue_id from tbl_magazine_issue WHERE magazine_id = 141
ORDER BY FROM_DATE DESC LIMIT 1) as temp_issue_id
FROM tbl_magazine_apps as tma
LEFT OUTER JOIN tbl_magazine_code as tmc ON tmc.Code = tma.AppsCode
LEFT OUTER JOIN `tbl_magazine` AS tm ON tmc.magazine_Id = tm.MAGAZINE_ID
JOIN `tbl_magazine_issue` AS tmi ON temp_issue_id = tmi.issue_id
LEFT OUTER JOIN mst_publisher AS pub ON tm.publisher_id=pub.publisher_id
WHERE
tmi.PUBLISH_STATUS IN(1,3)
AND tmi.`OS_SELECT` = '".$osType."'
AND tma.id IN (".$appIds.")
GROUP BY tm.MAGAZINE_ID
ORDER BY tmi.ISSUE_DATE DESC
but i got an error that
#1054 - Unknown column 'temp_issue_id' in 'on clause'
if any one know about this please help me. i am new to this
AFAIK The subquery belongs to the from part:
http://dev.mysql.com/doc/refman/5.7/en/from-clause-subqueries.html
So I would join the subquery.
Like:
SELECT a.a, b.b
FROM table1 as a
JOIN (SELECT b from table2) as b ON a.key = b.key;
As the message suggests, the column temp_issue_id is not in any of the following tables: tbl_magazine_apps, tbl_magazine, or tbl_magazine_issue. It is also not a variable in the environment.
Beyond that, it is pretty much impossible for anyone to figure out how to fix the problem without more knowledge about the data structure.
If I were to hazard a guess, based on the table names, that particular join would be:
JOIN `tbl_magazine_issue` AS tmi ON tm.magazine_id = tmi.magazine_id
because it makes sense to me that a magazine issue would be connect to a magazine. I have no idea what temp_issue_id is, though.
temp_issue_id give alias name for specifying this column i think it should be tm.issue_id
temp_issue_id is column's name as per the query. You need it to convert to table and use subsequent column in your SELECT clause.

mysql update query with sub query

Can anyone see what is wrong with the below query?
When I run it I get:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'a where a.CompetitionID = Competition.CompetitionID' at line 8
Update Competition
Set Competition.NumberOfTeams =
(
SELECT count(*) as NumberOfTeams
FROM PicksPoints
where UserCompetitionID is not NULL
group by CompetitionID
) a
where a.CompetitionID = Competition.CompetitionID
The main issue is that the inner query cannot be related to your where clause on the outer update statement, because the where filter applies first to the table being updated before the inner subquery even executes. The typical way to handle a situation like this is a multi-table update.
Update
Competition as C
inner join (
select CompetitionId, count(*) as NumberOfTeams
from PicksPoints as p
where UserCompetitionID is not NULL
group by CompetitionID
) as A on C.CompetitionID = A.CompetitionID
set C.NumberOfTeams = A.NumberOfTeams
Demo: http://www.sqlfiddle.com/#!2/a74f3/1
Thanks, I didn't have the idea of an UPDATE with INNER JOIN.
In the original query, the mistake was to name the subquery, which must return a value and can't therefore be aliased.
UPDATE Competition
SET Competition.NumberOfTeams =
(SELECT count(*) -- no column alias
FROM PicksPoints
WHERE UserCompetitionID is not NULL
-- put the join condition INSIDE the subquery :
AND CompetitionID = Competition.CompetitionID
group by CompetitionID
) -- no table alias
should do the trick for every record of Competition.
To be noticed :
The effect is NOT EXACTLY the same as the query proposed by mellamokb, which won't update Competition records with no corresponding PickPoints.
Since SELECT id, COUNT(*) GROUP BY id will only count for existing values of ids,
whereas a SELECT COUNT(*) will always return a value, being 0 if no records are selected.
This may, or may not, be a problem for you.
0-aware version of mellamokb query would be :
Update Competition as C
LEFT join (
select CompetitionId, count(*) as NumberOfTeams
from PicksPoints as p
where UserCompetitionID is not NULL
group by CompetitionID
) as A on C.CompetitionID = A.CompetitionID
set C.NumberOfTeams = IFNULL(A.NumberOfTeams, 0)
In other words, if no corresponding PickPoints are found, set Competition.NumberOfTeams to zero.
For the impatient:
UPDATE target AS t
INNER JOIN (
SELECT s.id, COUNT(*) AS count
FROM source_grouped AS s
-- WHERE s.custom_condition IS (true)
GROUP BY s.id
) AS aggregate ON aggregate.id = t.id
SET t.count = aggregate.count
That's #mellamokb's answer, as above, reduced to the max.
You can check your eav_attributes table to find the relevant attribute IDs for each image role, such as;
Then you can use those to set whichever role to any other role for all products like so;
UPDATE catalog_product_entity_varchar AS `v` INNER JOIN (SELECT `value`,`entity_id` FROM `catalog_product_entity_varchar` WHERE `attribute_id`=86) AS `j` ON `j`.`entity_id`=`v`.entity_id SET `v`.`value`=j.`value` WHERE `v`.attribute_id = 85 AND `v`.`entity_id`=`j`.`entity_id`
The above will set all your 'base' roles to the 'small' image of the same product.

Why Does My MySQL Query Using a Subselect Hang?

The following query hangs: (although subqueries perfomed separately are fine)
I don't know how to make the explain table look ok. If someone tells me, I'll clean it up.
select
sum(grades.points)) as p,
from assignments
left join grades using (assignmentID)
where gradeID IN
(select grades.gradeID
from assignments
left join grades using (assignmentID)
where ... grades.date <= '1255503600' AND grades.date >= '984902400'
group by assignmentID order by grades.date DESC);
I think the problem is with the first grades table... the type ALL with that many rows seems to be the cause.. Everything is indexed.
I uploaded the table as an image. Couldn't get the formatting right:
http://imgur.com/AjX34.png
A commenter wanted the full where clause:
explain extended select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t
from assignments left join grades using (assignmentID)
where gradeID IN
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type
where assignments.classID = '7815'
and (assignments.type = 30170 )
and grades.contactID = 7141
and grades.points REGEXP '^[-]?[0-9]+[-]?'
and grades.points != '-'
and grades.points != ''
and (grades.pointsposs IS NULL or grades.pointsposs = '')
and grades.date <= '1255503600'
AND grades.date >= '984902400'
group by assignmentID
order by grades.date DESC);
See "The unbearable slowness of IN":
http://www.artfulsoftware.com/infotree/queries.php#568
Super messy, but: (thanks for everyone's help)
SELECT *
FROM grades
LEFT JOIN assignments ON grades.assignmentID = assignments.assignmentID
RIGHT JOIN (
SELECT g.gradeID
FROM assignments a
LEFT JOIN grades g
USING ( assignmentID )
WHERE a.classID = '7815'
AND (
a.type =30170
)
AND g.contactID =7141
g.points
REGEXP '^[-]?[0-9]+[-]?'
AND g.points != '-'
AND g.points != ''
AND (
g.pointsposs IS NULL
OR g.pointsposs = ''
)
AND g.date <= '1255503600'
AND g.date >= '984902400'
GROUP BY assignmentID
ORDER BY g.date DESC
) AS t1 ON t1.gradeID = grades.gradeID
Suppose you use a Real Database (ie, any database except MySQL, but I'll use Postgres as an example) to do this query :
SELECT * FROM ta WHERE aid IN (SELECT subquery)
a Real Database would look at the subquery and estimate its rowcount :
If the rowcount is small (say, less than a few millions)
It would run the subquery, then build an in-memory hash of ids, which also makes them unique, which is a feature of IN().
Then, if the number of rows pulled from ta is a small part of ta, it would use a suitable index to pull the rows. Or, if a major part of the table is selected, it would just scan it entirely, and lookup each id in the hash, which is very fast.
If however the subquery rowcount is quite large
The database would probably rewrite it as a merge JOIN, adding a Sort+Unique to the subquery.
However, you are using MySQL. In this case, it will not do any of this (it is gonna re-execute the subquery for each row of your table) so it will take 1000 years. Sorry.
If your subquery performs fine when it is executed separately, then try using a JOIN rather than IN, like this:
select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t
from assignments left join grades using (assignmentID)
join
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type
where assignments.classID = '7815'
and (assignments.type = 30170 )
and grades.contactID = 7141
and grades.points REGEXP '^[-]?[0-9]+[-]?'
and grades.points != '-'
and grades.points != ''
and (grades.pointsposs IS NULL or grades.pointsposs = '')
and grades.date <= '1255503600'
AND grades.date >= '984902400'
group by assignmentID
order by grades.date DESC) using (gradeID);
There really isn't enough information to answer your question, and you've put a ... in the middle of the where clause which is weird. How big are the tables involved and what are the indexes?
Having said that, if there are too many terms in an in clause, you can see seriously degraded performance. Replace the use of in with a right join.
For starters, the table as_types in the in clause is not used. Left joining it serves no purpose so get rid of it.
That leaves the in clause having only the assignments and grades table from the outer query. Clearly the wheres the modify assignments belong in the where clause for the outer query. You should move all of the where grades=whatever into the on clause of the left join to grades.
The query is a little tough to follow, but I suspect that the subquery isn't necessary at all.
It seems like your query is basically thus:
SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)
WHERE gradeID IN
(
SELECT grades.gradeID
FROM assignments LEFT JOIN grades USING (assignmentID)
WHERE your_conditions = TRUE
);
But, you're not doing anything really fancy in the where clause in the subquery.
I suspect something more like
SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)
GROUP BY groupings
WHERE your_conditions_with_some_tweaks = TRUE;
would work just as well.
If I'm missing some key logic here please comment back and I'll edit/delete this post.