Alternative to in operator in mysql - mysql

I see In operator alternative in mysql
I have nearly 25,000 ids.I am using in operator on that.Then i am getting Stackoverflow Exception.Is there any other alternative for IN operator in mysql.
Thanks in advance..

If the ID's are in another table:
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
then you can use a join instead:
SELECT table1.* FROM table1 INNER JOIN table2 ON table1.id = table2.id;

You could do the following:
1 - Create a MySQL Temporary Table
CREATE TEMPORARY TABLE tempIdTable (id int unsigned not null primary key);
2 - Insert All Your ids into the Temporary Table
For every id in your list:
insert ignore into myId (id) values (anId);
(this will have the added bonus of de-duplicating your list of ids ready for the final step)
3 - Join Against the Temporary Table
SELECT t1.* FROM myTable1 t1 INNER JOIN tempIdTable tt ON t1.id = tt.id;
The temporary table will disappear as soon as your connection is dropped so your don't have to worry about dropping it before you create it next time.

Related

getting data from three different table and inserting it into new table

I have three tables with contents, now i want to get them and add it into new table but am having this sql error "Column count doesn't match value count at row 1"
here is the sql query.
insert into compare_year(yeara,yearb,yearc,data)
SELECT yeara
FROM table_1
UNION ALL
SELECT yearb, data
FROM table_2
UNION ALL
SELECT yearc
FROM table_3
below is how i created the tables
create table table_1(id int primary key auto_increment,yeara varchar(100));
create table table_2(id int primary key auto_increment,yearb varchar(100),data varchar(100));
create table table_3(id int primary key auto_increment,yearc varchar(100));
my new table is now
create table compare_year(id int primary key auto_increment,yeara varchar(100),yearb varchar(100),yearc varchar(100),data varchar(100))
please can someone help me. thanks
Note:when you union select queries,the number of columns should be equal.
and also you cannot insert mutiple select columns into a single row of another.
My solution will be like:
if three table contain same id,then you can do like this
insert into compare_year(yeara,yearb,yearc,data)
SELECT T1.yeara,T2.yearb,T3.yearc,T2.data
FROM table_1 T1
left Join table_2 T2 on T2.Id = T1.Id
left Join table_3 T3 on T3.Id = T2.Id
It looks like what you want is a JOIN rather than a UNION. When you union two select statements, they must have the same number of fields in the SELECT. For example,
insert into compare_year(yeara)
SELECT yeara
FROM table_1
UNION ALL
SELECT yearb AS yeara
FROM table_2
UNION ALL
SELECT yearc AS yeara
FROM table_3
would be acceptable syntactically. If you want to join the tables,
INSERT INTO compare_year(yeara, yearb, yearc, data)
SELECT table_1.yeara, table_2.yearb, table_3.yearc, table_2.data
FROM table_1, table_2, table_3
but note that this is full cartesian product of the tables. It's likely you want some conditionals as well in a WHERE clause. It's also worth noting that the order of the select cause is what's important for the INSERT, not the field names.

MySQL: Use a single Column to show as multiple select column in single row

Consider these example tables
E_id in Table1 is a primary key. From and Assign_to are foreign keys referenced with E_id.
I want to show a table like this:
I am not sure how I can implement it. Please share the SQL query which returns the desired table.
You could JOIN to Table1 twice:
SELECT
t2.work_name,
t1f.E_name AS `From`,
t1a.E_Name AS `Assign_to`
FROM Table2 t2
INNER JOIN Table1 t1f
ON t1f.E_id = t2.`from`
INNER JOIN Table1 t1a
ON t1a.E_id =t2.Assign_to
You can solve that problem with a simple temp table. It is not the most sophisticated way to solve it, but the solution is easy to comprehend.
The step are as followed:
Create a table with all data from table2
Add 2 columns to that table to store the name values for from and Assign_to
Update the columns with the name values from table1
Select your Data
MySQL-Code
-- create temp-table
CREATE TABLE table2_temp
SELECT * FROM table2;
-- add columns to enrich table with E_name from table1
ALTER TABLE table2_temp
ADD COLUMN E_name_from VARCHAR (125),
ADD COLUMN E_name_assign_to VARCHAR (125);
-- update temp-table with names from table1
-- for E_name_from
UPDATE table2_temp A
INNER JOIN table1 B ON (A.`from` = E_id)
SET A.E_name_from = B.E_name;
-- for E_name_assign_to
UPDATE table2_temp A
INNER JOIN table1.B ON (A.Assign_to = E_id)
SET A.E_name_assign_to = B.E_name;
-- now you can select your date from the temp-table
SELECT
work_name,
E_name_from AS `From`,
E_name_assign_to AS `Assign_to`
FROM
table2_temp;
-- drop table after work is done
drop table if exists table2_temp ;

I wanted to know the command to check if all the values in one field of a table is present in another table under a different field name

I have 2 tables. I want to find out whether the values present in the first table is there in another table with a different field name.
Here is how it looks,
Table1
BillNo
43529179
43256787
35425676
25467778
24354758
45754748
Table2
BNo
113104808
25426577
268579679
2542135464
252525232
235263663
I have 137 records in table1 that needs to be checked against table2.
Instead of doing it one by one using the following command,
Select * from Table2 where BNo = '43529179';
This gives the result for just the mentioned value. Is there a way to check for all the values in a single query?
Thanks!
You can use a sub-select to compare against:
Select * from Table2 where BNo IN (SELECT BillNo FROM Table1);
That will "evalaute" to something like Select * from Table2 where BNo IN (113104808, 25426577, 268579679, 2542135464, 252525232, ...);
Join the tables, and check how many matching records there are:
select
count(*) as Matches
from
Table1 as t1
inner join Table2 as t2 on t2.BNo = t1.BillNo
You can also use a left join to pick out the records in table 1 that has no matching record in table 2:
select
t1.BillNo
from
Table1 as t1
left join Table2 as t2 on t2.BNo = t1.BillNo
where
t2.BNo is null

SQL: insert only new records

This must be very trivial but I can't seem to find the solution.
I work with two tables, both without any primary key.
I want to add all the records of the first table to the second table only if they don't exist.
Basically:
INSERT INTO Table2
SELECT Table1.*
FROM Table
WHERE "the record to be added doesn't already exists in Table2"
You could do something like this. You would need to check each relevant column - I have just put in 2 as an example. With a Not Exists clause you can check if a record already existed across multiple columns. With a NOT IN you would only be able to check if a record already existed against one column.
INSERT INTO Table2
SELECT t1.*
FROM Table1 t1
WHERE NOT EXISTS
(
SELECT 1
FROM table2 t2 WHERE
t2.col1 = t1.col1 AND
t2.col2 = t1.col2
)
you could make usage of the EXISTS function:
INSERT INTO Table2
SELECT Table1.*
FROM Table1
WHERE NOT EXISTS(SELECT * FROM table2 WHERE <your expression to compare the two tables goes here>)
But i would advise you to check the use of unique index for your tables
Just an idea - untested:
INSERT INTO Table2
SELECT *
FROM Table1
WHERE NOT EXISTS(SELECT * FROM Table2 WHERE Table2.Field1 = Table1.Field1 AND Table2.Field2 = Table1.Field2)
You must add every Field of both Tables in the WHERE clause of the NOT EXISTS Query
INSERT INTO X.TableX1
(ColumX1,ColumnX2)
SELECT DISTINCT c.[ColumnY1],c.[ColumnY2]
FROM Y.Table2 c INNER JOIN Database.z.Table3 i ON c.ColumnX1= i.ColumnY1
WHERE NOT EXISTS
(
SELECT *
FROM X.TableX1 WHERE
X.TableX1.ColumnX1=c.ColumnY1
)
This is Joining two tables and filtering the data required and updating only the new values to third table on every run

Inner join and Split on large volume of data

We are working on large volume data (row counts given below) :
Table 1 : 708408568 rows -- 708 million
Table 2 : 1416817136 rows -- 1.4 billion
Table 1 Schema:
----------------
ID - Int PK
column2 - Int
Table 2 Schema
----------------
Table1ID - Int FK
SomeColumn - Int
SomeColumn - Int
Table1 has PK1 which servers as FK for Table 2.
Index details :
Table1 :
PK Clustered Index on Id
Non Clustered (Non Unique) on column2
Table 2 :
Table1ID (FK) Clustered Index
Below is the query which needs to be executed :
SELECT t1.[id]
,t1.[column2]
FROM Table1 t1
inner join Table2 t2
on s.id = cs.id
WHERE t1.[column2] in (select [id] from ConvertCsvToTable('1,2,3,4,5.......10000')) -- 10,000 Comma seperated Ids
So to summarize, The inner join on ID should be handled by the clustered index on the same Ids on both PK and FK.
and as for the "huge" Where condition on column2 we have a nonclustered index.
However, the query is taking 4 minutes for a small subset of 100 Ids, we need to pass 10,000 ids.
Is there a better way design wise that we can do this, or possibly does Table Partitioning help?
Just wanted to get some ways of how to solve huge volume Select with Inner Join and Where IN.
Note : ConvertCsvToTable is a Split function which has already been determined to perform optimally.
Thanks !
This is what I would try:
Create a temp table with the structure of the return from the function. Make sure to set the column ID as primary key so that the optimizer takes it into consideration...
CREATE TABLE #temp
(id int not null
...
,PRIMARY KEY (id) )
then call the function
insert into #temp exec ConvertCsvToTable('1,2,3,4,5.......10000')
then use the temp table directly joined in the query
SELECT t1.[id], t1.[column2]
FROM Table1 t1, t2, #temp
where t1.id = t2.id
and t1.[column2] = #temp.id
Bring the condition into the join
It gives the optimizer a chance to first filter by t1.[column2] first
Try different hash hints
SELECT t1.[id], t1.[column2]
FROM Table1 t1 with (nolock)
inner join Table2 t2 with (nolock)
on s.id = cs.id
and t1.[column2] in (select [id] from ConvertCsvToTable('1,2,3,4,5.......10000'))
You may need to tell it to use that index on Column2.
But give it a chance to do the right thing.
In the where you were not giving it a chance to do the right thing.
If you go with #temp then try
(and declare a PK on the temp as Rodolfo stated +1)
This will pretty much force it to start with small table
It could still get stupid do the join on T2 first but I doubt it.
SELECT t1.[id], t1.[column2]
FROM #temp
JOIN Table1 t1 with (nolock)
on t1.[column2] = #temp.ID
join Table2 t2 with (nolock)
on t2.ID = t1.ID