MySQL - Union in a filtering subquery - mysql

I'm able to run the following:
SELECT * FROM t1 WHERE t1.id NOT IN (SELECT id FROM t2);
As well as:
SELECT * FROM (SELECT id FROM t2 UNION SELECT id FROM t3);
But MySQL complains when I attempt to run the following:
SELECT * FROM t1 WHERE t1.id NOT IN (SELECT id FROM t2 UNION SELECT id FROM t3);
The error is "unexpected 'SELECT'" for the third select.
Is something wrong with my syntax? Is this not possible? I'm open to rewriting using EXISTS if that's the only way.

They are not mistakes on your query:
SQL Fiddle
MySQL 5.6 Schema Setup:
create table t1 ( id int );
create table t2 ( id int );
create table t3 ( id int );
insert into t1 values (1);
insert into t2 values (2);
insert into t3 values (3);
Query 1:
SELECT * FROM t1 WHERE t1.id NOT IN
(SELECT id FROM t2 UNION SELECT id FROM t3)
Results:
| id |
|----|
| 1 |

Related

SQL code to select records where field_A matches the field_A value of a certain field_B value

I have this table
ID Email
aa aa#gmail.com
aa aa#yahoo.com
bb bb#gmail.com
cc cc#hotmail.com
Using SQL code, I want to select all records that has the same ID as the ID of email aa#gmail.com. So it will return:
aa aa#gmail.com
aa aa#yahoo.com
I know that we can select records where field_A is a certain value like this:
SELECT * FROM tablename WHERE ID="aa"
How can I modify this code to achieve the desired results?
You can use a subquery:
SELECT t.*
FROM tablename t
WHERE t.ID = (SELECT t2.id
FROM tablename t2
WHERE t2.email = 'aa#gmail.com'
);
select * from tablename where id in (
SELECT ID AS count FROM tablename GROUP BY ID HAVING COUNT(ID) > 1
)
Using JOIN the same table ON ID, the result is possible:
SELECT T1.ID, T2.Email
FROM TableName T1
JOIN TableName T2 ON T2.ID = T1.ID
WHERE T1.Email = 'aa#gmail.com'
Demo on db<>fiddle
You can use SUBSTRING_INDEX
SELECT * FROM tablename WHERE ID=SUBSTRING_INDEX(`Email`, '#', 1) and Email='aa#gmail.com'
Instead of hardcoding it should return values after evaluating
CREATE TABLE TestTable (ID VARCHAR(5), Email VARCHAR (20));
INSERT INTO TestTable (ID, Email) VALUES
('aa', 'aa#gmail.com'),
('aa', 'aa#yahoo.com'),
('bb', 'bb#gmail.com'),
SELECT *
FROM TestTable
WHERE ID IN
(
SELECT CASE WHEN ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID)>1 THEN ID END AS ID
FROM TestTable
)

Conditional SELECT SQL with relational tables

Say I have an id in table1 which is a foreign key in table2 and there is a column in table2 called condition.
I need to select all ids from table 1 that aren't in table2 where condition = 1.
So for id in table 1 "select it" if it is not in table2 where condition = 1.
Edit: I used Ahsan Habib's answer and it worked great!
if you just want to select ID column from table1 this will work fine....Its just a simple set operation
select id from t1
minus
select id from t2 where condition = 1;
for all column you may try
select * from t1 whare id not in (select id from t2 where condition = 1);
This is almost a direct translation of what you are asking for:
select t1.*
from table1 t1
where t1.id not in (select t2.id from table2 t2 where t2.condition = 1);
Another way using NOT EXISTS
select t1.*
from table1 t1
where NOT EXISTS(select 1 from table2 t2 where t1.id = t2.id and t2.condition = 1);

Update Query in SQL Server via JOINS

I have 2 tables as mentioned below
create table #temp(id int, userid int,age int)
insert into #temp values (1,1,1)
insert into #temp values(2,1,2)
insert into #temp values(3,1,3)
create table #tempMOCK(id int, userid int,age int)
insert into #tempMOCK values (6,1,7)
insert into #tempMOCK values (7,1,9)
I want to update the first 2 rows of Mock table on #temp table. I am expecting that age of rowids 2 & 3 should become 7 & 9. I'm using this query but somehow it doesn't work.
UPDATE t1
SET t1.age = t2.age
FROM #temp t1
INNER JOIN #tempMOCK t2 ON t1.userid = t2.userid where t1.id in (1,2)
Since the user id is the same in all rows, you get the same value for the age.
This can be solved using a CTE, like this:
;with cte as
(
select id, userid, age, ROW_NUMBER() OVER(order by id) rn
FROM #tempMock
)
UPDATE t1
SET t1.age = t2.age
FROM #temp t1
INNER JOIN cte t2 ON t1.userid = t2.userid and t1.id = t2.rn+1;
see fiddle here
you can try following query for this:
UPDATE #temp1 set age=(Select t2.age from #tempMOCK t2
where t2.userid=#temp1.userid) where id in (1,2)
Hope it helps

MySQL subquery using INSTR

The query below will select all of the name records from table 1, which are NOT IN table 2:
SELECT t1.name
FROM t1
WHERE t1.name NOT IN (SELECT t2.name from t2)
This works fine for complete matches of the name field, but it does not work for partial matches. How can I modify the query so that it will select only the name records from table 1 where no part of the name appeals in table 2?
I suspect that the answer is going to involve using INSTR, but I'm not sure of the syntax. Thanks.
JOIN will do the job
CREATE TABLE test1 (
name VARCHAR(10);
)
CREATE TABLE test2 (
name VARCHAR(10);
)
INSERT INTO test1 VALUES
( 'x123' ),
( 'y123' ),
( 'z123' );
INSERT INTO test2 VALUES
( '123' ),
( '423' ),
( '23' );
SELECT t1.name, t2.name
FROM test1 t1
JOIN test2 t2
ON INSTR(t1.name, t2.name ) = 0
ORDER BY t1.name;

Creating a View that returns the first occurrence of a value

I'm trying to create a view that returns the first occurrence of a value.
I have two tables
First table:
sID | dt
12 | DateTimeValue1
12 | DateTimeValue2
second table:
S_ID
12
I want the view to join both tables and give me the first occurance of S_ID (in this case DateTimeValue1)
How can I accomplish this?
More Info:
in table 1 I have two columns sID and dt. Values for these columns look like this:
sID: 1 dt: 2014-06-12
sID: 1 dt: 2014-06-13
sID 1 dt: 2014-06-14 etc...
I want to join the two tables in my view so that
where S_ID matches sID it returns the first value (in this case 2014-06-12)
Sorry for any confusion!
Here's what I got so far:
This is what I got so far:
CREATE VIEW view_name AS
SELECT [S_ID]
FROM table1
LEFT JOIN table2
ON table1.[S_ID]=table2.sID;
You could do something like : http://sqlfiddle.com/#!3/66ee02/1
create view theview as
select
t1.s_id, min(dt) dt
from
table1 t1 inner join
table2 t2 on t1.s_id = t2.s_id
group by
t1.s_id
In MS SQL Server you can select the first row of table1 and join it with table2 in a view like this:
create view view_name
as
select table1.*,table2.*
from table2
inner join
(select top 1 *
from table1
order by table1.what_ever_field) as table1
on table2.id = table1.id
This works well if table2 has a foreign key to table1.
If they are independent tables with no foreign keys You can do this:
create view view_name
as
select table1.*,table2.*
from (select top 1 * from table2 order by table2.field1) as table2
,
(select top 1 * from table1 order by table1.field1) as table1
Please try :
select t1.sID,min(t1.dt) from first_table t1, second_table t2 where t1.sID=t2.sID group by t1.sID
I tried same with below code in sybase and it worked well.
create table #temp1
(sID int,dt date)
create table #temp2
(sID int)
insert into #temp1
select 12,getdate()
insert into #temp1
select 12,getdate()
insert into #temp1
select 12,getdate()
insert into #temp2
select 12
insert into #temp1
select 13,getdate()
insert into #temp2
select 13
insert into #temp1
select 14,getdate()
insert into #temp1
select 14,getdate()
insert into #temp2
select 14
select * from #temp1
select * from #temp2
select t1.sID,min(t1.dt) from first_table t1,
second_table t2
where t1.sID=t2.sID
group by t1.sID