UPDATE tab1
SET col = 1
FROM tab1
LEFT JOIN tab2 ON tab2.ID = tab1.ID
WHERE tab2.ID IS NULL
Where do I put the ELSE col = 0in this query?
UPDATE tab1
SET col = CASE WHEN tab2.ID IS NULL THEN 1 ELSE 0 END
FROM tab1
LEFT JOIN tab2 ON tab2.ID = tab1.ID
I assume you want col to be 1 when tab2.ID is NULL and 0 when it is not. So you need to do 2 things. Use a case expression. Also remove your where expression so that you are not limiting the results table to only tab1 rows that have no relation to tab2
Related
I have 3 tables in which there are about 70 columns combined.
What I am trying to do is select everything from 1 and 2 but then there are certain conditions to get first and last score and those are in third table.
SELECT
ID, NAME, TIME, ROUNDS
(SELECT SCORE
FROM TABLE2 TAB2
JOIN TABLE3 TAB3 ON TAB2.ID = TAB3.ID
WHERE PARAMETER1 = 9 AND PARAMETER2 = 21) AS FIRST,
(SELECT SCORE
FROM TABLE2 TAB2
JOIN TABLE3 TAB3 ON TAB2.ID = TAB3.ID
WHERE PARAMETER1 = 15 AND PARAMETER2 = 2) AS LAST
FROM
TABLE1 TAB1
JOIN
TABLE2 TAB2 ON TAB1.ID = TAB2.ID
GROUP BY
ID, NAME, TIME, ROUNDS
I get the following error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I also tried to do the joins at the end and I do get a result but it is wrong
SELECT
ID, NAME, TIME, ROUNDS
(SELECT SCORE
WHERE PARAMETER1 = 9 AND PARAMETER2 = 21) AS FIRST,
(SELECT SCORE
WHERE PARAMETER1 = 15 AND PARAMETER2 = 2) AS LAST
FROM
TABLE1 TAB1
JOIN
TABLE2 TAB2 ON TAB1.ID = TAB2.ID
JOIN
TABLE3 TAB3 ON TAB2.ID = TAB3.ID
I get incorrect data because I cannot group it since it wants me to group parameters as well
Msg 8120, Level 16, State 1, Line 46
Column 'PARAMETER1' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I really don't know what I'm doing wrong so is there any way you guys can help ?
As I mentioned in the comments, you need to correlate your subqueries, and I suspect that you think that all 3 references to TABLE2 TAB2 are the same instance of said object. This is a flawed understanding. Each time you reference an object it is a new "instance" of it.
As such what you likely want is this:
SELECT TAB1.ID,
TAB1.NAME,
TAB2.TIME,
TAB2.ROUNDS,
(SELECT TAB3.SCORE
FROM dbo.TABLE3 TAB3
WHERE TAB3.ID = TAB2.ID
AND TAB3.PARAMETER1 = 9
AND TAB3.PARAMETER2 = 21) AS FIRST,
(SELECT TAB3.SCORE
FROM dbo.TABLE3 TAB3
WHERE TAB3.ID = TAB2.ID
AND TAB3.PARAMETER1 = 15
AND TAB3.PARAMETER2 = 2) AS LAST
FROM dbo.TABLE1 TAB1
JOIN dbo.TABLE2 TAB2 ON TAB1.ID = TAB2.ID;
Or perhaps you would be better off with conditional aggregation, which would mean 1 scan of the table dbo.TABLE3:
SELECT TAB1.ID,
TAB1.NAME,
TAB2.TIME,
TAB2.ROUNDS,
MAX(CASE WHEN TAB3.PARAMETER1 = 9 AND TAB3.PARAMETER2 = 21 THEN TAB3.Score END) AS FIRST,
MAX(CASE WHEN TAB3.PARAMETER1 = 15 AND TAB3.PARAMETER2 = 2 THEN TAB3.Score END) AS FIRST
FROM dbo.TABLE1 TAB1
JOIN dbo.TABLE2 TAB2 ON TAB1.ID = TAB2.ID
JOIN dbo.TABLE3 TAB3 ON TAB2.ID = TAB3.ID
GROUP BY TAB1.ID,
TAB1.NAME,
TAB2.TIME,
TAB2.ROUNDS;
Note that the tables the columns belong to is guessed. If incorrect, you'll need to correct.
it seems below nested queries return multiple values .
(SELECT SCORE
WHERE PARAMETER1 = 9 AND PARAMETER2 = 21) AS FIRST
(SELECT SCORE
WHERE PARAMETER1 = 15 AND PARAMETER2 = 2) AS LAST
You should use top(1) with order by ascending for first and descending for last column as below.
SELECT
ID, NAME, TIME, ROUNDS
(SELECT top(1) SCORE
WHERE PARAMETER1 = 9 AND PARAMETER2 = 21 order by SCORE asc ) AS FIRST,
(SELECT top(1) SCORE
WHERE PARAMETER1 = 15 AND PARAMETER2 = 2 order by SCORE desc ) AS LAST
FROM
TABLE1 TAB1
JOIN
TABLE2 TAB2 ON TAB1.ID = TAB2.ID
JOIN
TABLE3 TAB3 ON TAB2.ID = TAB3.ID
I think above query helps you finding error on exact location.
I have a SQL query which takes a lot of time to execute.
It goes like this
select
columns
from
tab1
where
tab1.id in (select col from tab2 where conditions) --32000 rows
or
tab1.id in (select col from tab3 where conditions) ---14000 rows
or
tab1.id in (select col from tab4 where conditions) --6000 rows
Is there any way I can increase the performance here?
I've tried using EXISTS() too but that did not help.
Oracle should be pretty good with optimizing queries that have in with a subquery. Your best bet is adding indexes. However, your query is not detailed enough to suggest particular indexes. You need to be explicit about the where clause.
option1:
select
columns
from
tab1
where
tab1.id in (select col from tab2 where conditions --32000 rows
union all
select col from tab3 where conditions ---14000 rows
union all
select col from tab4 where conditions --6000 rows
);
option2:
select
columns
from
tab1
inner join (select distinct col
from (select col from tab2 where conditions --32000 rows
union all
select col from tab3 where conditions ---14000 rows
union all
select col from tab4 where conditions --6000 rows
)
) x
on tab1.id = x.col;
option3:
select
columns
from
tab1
where
exists (select col from tab2 where conditions --??? rows
where col = tab1.id
union all
select col from tab3 where conditions ---??? rows
where col = tab1.id
union all
select col from tab4 where conditions --??? rows
where col = tab1.id
);
I have three tables Tab1, Tab2 and Tab3 with almost same structre (in MS Access). But Tab2 and Tab3 have a few more columns than Tab1.
Tab2 and Tab3 are exactly same structure. Following are the joining keys
col1
col2
col3
Basically Tab1 records should tally with Tab2 and Tab3 together.
If I need to get the missing records in Tab2 and Tab3 when compare to Tab1 what could be the efficient way
Appreciate your response
If you only care about the keys, here is a good approach:
select col1, sum(isTab1) as numTab1, sum(isTab2) as numTab2, sum(isTab3) as numTab3
from ((select col1 as col, 1 as isTab1, 0 as isTab2, 0 as isTab3 from tab1
) union all
(select col2, 0 as isTab1, 1 as isTab2, 0 as isTab3 from tab2
) union all
(select col3, 0 as isTab1, 0 as isTab2, 1 as isTab3 from tab3
)
) t
group by col
having sum(isTab1)*sum(isTab2)*sum(isTab3) <> 1
This returns each of the key values and tells you which tables they are in and not in, for keys that are not in all three tables. As a bonus, this will also tell you if any of the tables have duplicate keys.
usually you would SELECT FROM tab1 LEFT JOINing the tab2 and tab3 LEFT JOINed together. That way you will get ALL records from tab1. When there are some missing records in tab2 and tab3 there will be nulls. You can check for nulls in the WHERE clause
So, the query would look similar to this one (please note the brackets - it is a requirement for ms-access):
SELECT * FROM
tab1 LEFT JOIN (tab2 LEFT JOIN tab3 ON tab2.col1 = tab3.col1 AND tab2.col2 = tab3.col2)
ON tab1.col1 = tab2.col1 AND tab1.col2 = tab2.col2
WHERE tab2.col1 Is Null;
I need help in simplifying the below query.
I was able to check for '0' count without using Group By/having Count clauses in the below query but with correlated subquery.
Now, I've been asked to simplify the below query as simple joins!.
I tried merging the query into one. But the output differs.
Could you please suggest any other idea of simplifying the query, which is checking for '0' count.
select distinct tab1.col1
from tab1
where tab1.col2 = 'A'
And 0 = (select count(tab2.col1)
from tab2
where tab2.col2 = 'B'
and tab2.col1 = tab1.col1)
This sort of thing would normally be written as a NOT EXISTS
SELECT distinct tab1.col1
FROM tab1
WHERE tab1.col2 = 'A'
AND NOT EXISTS(
SELECT 1
FROM tab2
WHERE tab2.col2 = 'B'
AND tab2.col1 = tab1.col1 )
However you could also write
SELECT tab1.col1, count(tab2.col1)
FROM (SELECT * FROM tab1 WHERE col2 = 'A') tab1,
(SELECT * FROM tab2 WHERE col2 = 'B') tab2
WHERE tab1.col1 = tab2.col2(+)
GROUP BY tab1.col1
HAVING count(tab2.col1) = 0
Try some of these.
If col1 is declared as not null, the first two queries have the same execution plan (anti-joins). The second alternative is my personal advice, since it matches your requirements the best.
-- Non-correlated subquery
select distinct col1
from tab1
where col2 = 'A'
and col1 not in(select col1
from tab2
where col2 = 'B');
-- Correlated subquery
select distinct col1
from tab1
where col2 = 'A'
and not exists(select 'x'
from tab2
where tab2.col2 = 'B'
and tab2.col1 = tab1.col1);
-- Using join
select distinct tab1.col1
from tab1
left join tab2 on(tab2.col2 = 'B' and tab2.col1 = tab1.col1)
where tab1.col2 = 'A'
and tab2.col1 is null;
-- Using aggregation
select tab1.col1
from tab1
left join tab2 on(tab2.col2 = 'B' and tab2.col1 = tab1.col1)
where tab1.col2 = 'A'
group
by tab1.col1
having count(tab2.col2) = 0;
I have an oracle sql query
select
distinct
tab1.col1,
tab2.col1
from
table1 tab1
join table2 tab2 on tab1.col1 = tab2.col1
Here i get the as expected in terms of distinct values.
For Example : The result rows are
1 2
3 4
5 6
Now I want to add one more join for table3. so my sql is
select
distinct
tab1.col1,
tab2.col1,
tab3.col1
from
table1 tab1
join table2 tab2 on tab1.col1 = tab2.col1
join table3 tab3 on tab1.col1 = tab3.col1
Here what the problem is is that table 3 is returning more than one value.
which is resulting in duplicate rows based on table3.
For Example : The result rows are
1 2 4
1 2 5
3 4 1
3 4 2
5 6 3
(Here if you notice row 1 & 2 are duplicate and 3 & 4 are duplicate)
What I am trying to do is for the join of table3 i want to fetch the
first occurrence of row.
This shud work for you !
select
distinct
tab1.col1,
tab2.col1,
MIN(tab3.col1)
from
table1 tab1
join table2 tab2 on tab1.col1 = tab2.col1
join table3 tab3 on tab1.col1 = tab3.col1
GROUP BY tab1.col1, tab2.col1
Edit: Thoughts,
I am assuming column 3 to be a integer which ever increasing, in that case this works. You can use the date column to define your aggregate accurately to get the "first occurance of your row".
select
distinct
tab1.col1,
tab2.col1,
t3.col1
from
table1 tab1
join table2 tab2 on tab1.col1 = tab2.col1
join (select distinct col1 from table3) t3 on tab1.col1 = t3.col1