Is there any way we can do this in SQL?
Les say I have table Tablename_1 as below:
id
col1
1
data1
2
data2
3
data3
4
data4
5
data5
I want to check if the data I have in my where clause is present in the table or not
for example, where clause is as:
where id in (1,3,5,7);
Then I wish to output as below:
id
data_result
1
YES
3
YES
5
YES
7
NO
There are a few ways to do this.
One option is to provide your IDs as a table-valued constructor (VALUES() clause) instead of a WHERE clause. Then you can LEFT JOIN from this new "table" to create your result.
This is the MySql version (Postgresql needs to remove the row keywords):
select a.n, case when t1.id IS NULL then 'N' else 'Y' end as data_result
from (values row(1), row(3),row(5),row(7)) as a(n)
left join tablename_1 t1 on a.n = t1.id
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=028e5a984e5ed2969247e025bc8776be
You can also do this in a CTE via UNION:
WITH base as (
SELECT 1 as n UNION SELECT 3 UNION SELECT 5 UNION SELECT 7
)
SELECT base.n, case when t1.id IS NULL then 'N' else 'Y' end as data_result
FROM base
LEFT JOIN tablename_1 t1 on base.n = t1.id
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=ef2a88f6f89bf4101d7d651b4440ac28
This works the same in both databases, but as you can see means building a up lot more code per value in your list.
A final option is creating a dynamic numbers table. Then you can again LEFT JOIN these tables together to find out the Yes/No result for all possible values in the dynamic table and then still put your desired values in a WHERE clause to only show those results. The trick here is it requires you to have some idea of the possible scope for your values up front, and can make things a little slower if your guess is too far off.
Any of these could also be written to use an EXISTS() clause, which can often perform better. I just find the JOIN easier to write and reason about.
You could also use exists with the values approach from Joel
Something like
select v.*,
case when exists(select 1 from Tablename_1 as t where t.id=v.id) then
'Yes'
else
'No'
end
from (values (1),(3),(5),(7)) as v(id)
You can use ANY.
select Tablename_1.id,
case
when Tablename_1.id = ANY (ARRAY[1, 3,5,7])
then 'YES'
else 'NO' end
as data_result
from Tablename_1;
further reading: IN vs ANY operator in PostgreSQL
Related
id name redirect_id
1 .... NULL
2 ..... NULL
3 ..... 2
4 .... NULL
5 .... 1
i have this table. id is primary key. I want to get name of the row. However if it has a redirect_id, i want to get redirected id's name. Is there a possible way to do it in one sql query?
I know how to do it after fetching the result array. However it becomes so tangled if i do it that way. 1 sql query would be so good here. Thanks.
edit i need all redirected row not just redirrected name.
select ln.id
, COALESCE(ln2.name, ln.name)
from linkednames ln
left join linkednames ln2 on ln2.id = ln.redirect_id
If there is only one hop, then this is a simple join:
select t.id, (case when t.redirect_id is null then t.name else tr.name end) as name
from t left join
t tr
on t.redirect_id = tr.id;
If re-directs can have re-directs, you'll need more joins. MySQL does not have good support for hierarchical/recursive queries.
i have an SQL Requests:
SELECT DISTINCT id_tr
FROM planning_requests a
WHERE EXISTS(
SELECT 1 FROM planning_requests b
WHERE a.id_tr = b.id_tr
AND trainer IS NOT NULL
AND trainer != 'FREE'
)
AND EXISTS(
SELECT 1 FROM planning_requests c
WHERE a.id_tr = c.id_tr
AND trainer IS NULL
)
but this requests take 168.9490 sec to execute for returning 23162 rows of 2545088 rows
should i use LEFT JOIN or NOT IN ? and how can i rewrite it thx
You can speed this up by adding indexes. I would suggest: planning_requests(id_tr, trainer).
You can do this as:
create index planning_requests_id_trainer on planning_requests(id_tr, trainer);
Also, I think you are missing an = in the first subquery.
EDIT:
If you have a lot of duplicate values of id_tr, then in addition to the above indexes, it might make sense to phrase the query as:
select id_tr
from (select distinct id_tr
from planning_requests
) a
where . . .
The where conditions are being run on every row of the original table. The distinct is processed after the where.
I think your query can be simplified to this:
SELECT DISTINCT a.id_tr
FROM planning_requests a
JOIN planning_requests b
ON b.id_tr = a.id_tr
AND b.trainer IS NULL
WHERE a.trainer < 'FREE'
If you index planning_requests(trainer), then MySQL can utilize an index range to get all the rows that aren't FREE or NULL. All numeric strings will meet the < 'FREE' criteria, and it also won't return NULL values.
Then, use JOIN to make sure each record from that much smaller result set has a matching NULL record.
For the JOIN, index planning_requests(id_tr, trainer).
It might be simpler if you don't mix types in a column like FREE and 1.
I have a list of ids, and I want to query a mysql table for ids not present in the table.
e.g.
list_of_ids = [1,2,4]
mysql table
id
1
3
5
6
..
Query should return [2,4] because those are the ids not in the table
since we cant view ur code i can only work on asumption
Try this anyway
SELECT id FROM list_of_ids
WHERE id NOT IN (SELECT id
FROM table)
I hope this helps
There is a horrible text-based hack:
SELECT
substr(result,2,length(result)-2) AS notmatched
FROM (
SELECT
#set:=replace(#set,concat(',',id,','),',') AS result
FROM (
select #set:=concat(',',
'1,2,4' -- your list here
,',')
) AS setinit,
tablename --Your tablename here
) AS innerview
ORDER BY LENGTH(result)
LIMIT 1;
If you represent your ids as a derived table, then you can do this directly in SQL:
select list.val
from (select 1 as val union all
select 2 union all
select 4
) list left outer join
t
on t.id = list.val
where t.id is null;
SQL doesn't really have a "list" type, so your question is ambiguous. If you mean a comma separated string, then a text hack might work. If you mean a table, then something like this might work. If you are constructing the SQL statement, I would advise you to go down this route, because it should be more efficient.
Ive seen plenty of examples but none seem to get me where I need it.
I want to Select 1 field from table A, then Check table B for a value, if that value is true(boolean) then also Select field 2 and 3 from table A to return all 3 fields. So if value from B is false only 1 field is selected from table A, if true, all 3 are selected.
Select Field1
, Case
When Exists (
Select 1
From TableB
Where SomeField = 1
And ...
) Then TableA.Field2
Else Null
End As Field2
, Case
When Exists (
Select 1
From TableB
Where SomeField = 1
And ...
) Then TableA.Field3
Else Null
End As Field3
From TableA
Update
The above solution works fine if what you want is a three column result every time even if some of those columns are null. However, if what you want is a different number of columns returned based on the query, then this is something that cannot be done in a single query. The SQL language was not geared to handle on-the-fly schema generation. My suggestion would first be to evaluate why you want a different number of columns from the same query and determine if you cannot simply handle the scenario in your middle-tier where column 2 or 3 is NULL. That is by far the simplest solution and could be done in a single query:
Select TableA.Field1, TableA.Field2, TableA.Field3
, (
Select TableB.SomeBooleanColumn
From TableB
) As TableBValue
From TableA
Your middle-tier code would then determine whether to do something with Field2 and Field3.
That said, if you insist on having two column structures, you need two queries:
Select TableA.Field1
From TableA
Where Exists (
Select 1
From TableB
Where TableB.SomeColumn = 0
)
After calling this query, you would evaluate whether you got a row. If you got no rows, you could then call this query:
Select TableA.Field1, TableA.Field2, TableA.Field3
From TableA
Where Exists (
Select 1
From TableB
Where TableB.SomeColumn = 1
)
What hasn't be stated in the OP is the scenario where there is no row in TableB.
Use case expressions:
select A.field1,
case B.boolValue when 1 then A.field2 end AS field2,
case B.boolValue when 1 then A.field3 end AS field3
from TableA A join TableB B on A.? = B.?
I don't know what your A and B tables are linked on so you'll have to fill in the ? marks. This will return null values for field2 and field3 when B.boolValue is false.
I am trying to run a query to remove a set of ID's from a table when they are present in a field from another table.
The problem is both ID fields are of type text and the search does not appear to be case sensitive (but I need it to be). (i.e. ABC123 is different than abc123)
I am running a query similar to Select myID from table1 where myID NOT IN (Select otherID from table2)
What modification do I need to make in my Access query to make the results case sensitive when running comparison?
Try this:
SELECT a.*
FROM table1 a LEFT JOIN table2 b
ON a.myID = b.otherID
WHERE StrComp(IIF(IsNull(b.otherID ), a.myID , b.otherID), a.myID, 0) <> 0
OR IsNull(b.otherID)