I have three tables emp, d1, d2. Tables d1 and d2 have almost same structure.
I need to join emp table with either d1 or d2 depending on the value of column deptno in emp table. My query which I have written is not working and giving syntax error:
Error Code: 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 'CASE
SELECT
e.`empno`,
e.`ename`,
e.`job`,
e.`mgr`,
e.`hiredate`,
e.`sal`,
e.`comm`,
e.`deptno`
FROM
`emp` e
JOIN
CASE
WHEN e.deptno <= 20
THEN
d1 ON e.deptno = d1.`deptno`
ELSE
d2 ON e.deptno = d2.`deptno`
END;
There is no such thing as a "conditional" join. You can do:
SELECT e.*,
COALESCE(d1.col1, d2.col1) as col1
FROM emp e LEFT JOIN
d1
ON e.deptno = d1.deptno AND e.deptno <= 20 LEFT JOIN
d2
ON e.deptno = d2.deptno AND e.deptno > 20;
Note that your query does not not select anything from the d1 or d2. In that sense, the JOIN is not needed at all. Note the logic in the SELECT for getting values from columns.
If you are using the joins for filtering, then add:
WHERE d2.deptno IS NOT NULL OR d1.deptno IS NOT NULL.
This is what a UNION SELECT is for:
SELECT e.`empno`, e.`deptno`
FROM `emp` e JOIN d1 ON e.deptno = d1.`deptno`
WHERE e.deptno <= 20
UNION
SELECT e.`empno`, e.`deptno`
FROM `emp` e JOIN d2 ON e.deptno = d2.`deptno`
WHERE e.deptno > 20
Just make sure that both selects pick same amount and type of columns.
Related
I was working on Oracle to MySQL query conversion when I encountered the following snippet that I'm completely unable to understand:
select *
from a, b
where a.liab_id = b.liability_no(+)
and NVL (a.cust_id, b.customer_no(+)) = b.customer_no(+);
Table a columns: cust_id, liab_id, details
Table b columns: customer_no, liability_no,range
I'd be really grateful if someone can explain the query or convert it to the respective MySQL query.
To convert the legacy Oracle comma join to the ANSI join syntax, you want:
SELECT *
FROM a
LEFT OUTER JOIN b
ON ( a.liab_id = b.liability_no
AND COALESCE( a.cust_id, b.customer_no ) = b.customer_no
)
or
SELECT *
FROM a
LEFT OUTER JOIN b
ON ( a.liab_id = b.liability_no
AND ( a.cust_id = b.customer_no OR a.cust_id IS NULL )
)
Oracle 18c db<>fiddle here
MySQL 8 db<>fiddle here
In both Oracle and MySQL, you should use explicit JOIN syntax. That would be:
select *
from a left join
b
on a.liab_id = b.liability_no and
a.cust_id = b.customer_no;
I have written the following query wherein I am usig groupby clause on server column
select s.server, MAX(s.ipAddress) as ipAddress,
MAX(r.stacks->>"$[0].name") as stackName,
MAX(a.aMessage) as aMessage
from environments e
inner join servers s
on e.objectId = s.environmentId
inner join resources r
on e.objectId = r.environmentId
inner join audits a
on a.id = (select max(a.id) from audits a where a.logObjId = s.cAudit)
WHERE dateSubmitted BETWEEN NOW() - INTERVAL 90 DAY AND NOW()
Group by s.server
ORDER BY dateSubmitted;
Howerver, server column may have NULL values with a valid ipAddress and stackName.
How to modify the query so that all NULL server column values are not missed out.
Expected Sample Data:
server ipAddress stackName aMessage
NULL NULL Stack A Searching for IP pool
NULL NULL Stack B Message XYZ
NULL NULL Stack A Message ABC
It seems the INNER JOIN used to JOIN the table makes NULL value to removed from the result. So just modified the query. Try this one and see if you are able to see all the data of Server table so that NULL data also will come for Server column.
select s.server, MAX(s.ipAddress) as ipAddress,
MAX(r.stacks->>"$[0].name") as stackName,
MAX(a.aMessage) as aMessage
from servers s
left join environments e
on e.objectId = s.environmentId
left join resources r
on e.objectId = r.environmentId
left join audits a
on a.id = (select max(a.id) from audits a where a.logObjId = s.cAudit)
WHERE dateSubmitted BETWEEN NOW() - INTERVAL 90 DAY AND NOW()
Group by s.server
ORDER BY dateSubmitted;
I am trying to change the value of a column table with a sum function, this is my code:
For example
c.total = (10-2-3) - (3)
c.total = 2
update tabC c
JOIN tabB b ON b.c_id = c.id
set c.total = (c.v1 - c.v2 - c.v3) - IF(sum(b.payment) is not null, sum(b.payment), 0)
where c.id= 983;
but I get the following error:
ERROR 1111 (HY000): Invalid use of group function
I think the error is sum, but how can I solve that?
Thanls in advance
You need to join with a subquery that uses GROUP BY.
UPDATE tabC c
LEFT JOIN (
SELECT c_id, SUM(payment) AS total_payment
FROM tabB
GROUP BY c_id) AS b ON b.c_id = c.id
SET c.total = (c.v1 - c.v2 - c.v3) - IFNULL(b.total_payment, 0)
WHERE c.id = 983
You should usee a nested subquery whit aggregated resutl for join
update tabC c
JOIN (
select c_id, ifnull(sum(payment),0) tot_payment
from tabB
group by c_id
) b ON b.c_id = c.id
set c.total = (c.v1 - c.v2 - c.v3) - b.tot_payment
where c.id= 983;
The following query fails to be parsed:
select t.ename, t.received, d.loc from
(
select e.ename, eb.received , e.deptno
from emp e left outer join emp_bonus eb
on
e.empno=eb.empno
)
as t
join dept as d on d.deptno = t.deptno;
with the error:
Column 'deptno' in field list is ambiguous
But this query is parsed succesfully:
select t.ename, t.received, d.loc from
(
select e.ename, eb.received , e.deptno
from emp e left outer join emp_bonus eb
on
e.empno=eb.empno
)
as t, dept as d where d.deptno = t.deptno
I only changed the JOIN ON to t, dept where
Why does the first version fail?
the first query runs perfectly in mysql version 5.1
see the demo
I have two tables that share the same column (C) but SQL tells me I have an error
Here is the first table from the first query:
SELECT E.C AS C,
COUNT(C) AS CC
FROM E
GROUP BY E.C
And here is the second query:
SELECT E.C AS C,
COUNT(C) AS Num
FROM E, G
WHERE E.G = G.L
AND G.G <
(SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C
So I tried to simply put these two together by putting JOIN in between them. But this doesn't join them, even though they share the same column C. It simply says I have a syntax error. What is wrong? And how do I fix it? I have confirmed that when run separately, they produce the correct output with a column C
Below is the total JOIN execution
(SELECT E.C AS C,
COUNT(C) AS CC
FROM E
GROUP BY E.C)
JOIN
(SELECT E.C AS C,
COUNT(C) AS Num
FROM E, G
WHERE E.G = G.L
AND G.G <
(SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C)
And the error is
Error code 1064, SQL state 42000: 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 'JOIN
(SELECT E.C AS C,
COUNT(C) AS Num' at line 6
Line 1, column 1
You did not show your syntax error but, I am guessing your has to do with the following line:
COUNT(C) AS CC
Since both tables have a column C, the query does not know which table to return the value from. You need to preface it with the table name or alias.
This line works in your first query because you only had one column called C, once you have two you need to specify which one you want to return.
Based on your edit, you are missing aliases for the subqueries and the on condition for the join:
select t1.C, t1.cc, t2.num
from
(
SELECT E.C AS C,
COUNT(C) AS CC
FROM E
GROUP BY E.C
) t1 -- added alias
INNER JOIN
(
SELECT E.C AS C,
COUNT(E.C) AS Num -- added table name, since column c exists in both tables
FROM E
JOIN G
ON E.G = G.L
WHERE G.G < (SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C
) t2 -- added alias
on t1.C = t2.C -- added on clause
Try this:
select Z.C /*other*/
from (SELECT E.C AS C,
COUNT(E.C) AS CC
FROM E
GROUP BY E.C) Z
JOIN (SELECT E.C AS C,
COUNT(E.C) AS Num
FROM E, G
WHERE E.G = G.L
AND G.G < (SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C) Y on Y.C = Z.C