Inserting values from two tables into a new table - mysql

I ran this query:
Insert into transaction(matric,surname,other,level,bk_id,bk_title)
values(
(select matric,surname,others,level from member_master),
(select isbn,bk_title from book_master)
)
but I got this error:
column count doesn't match value count at row 1

You have to use the same columns which you have mentioned in the insert statement. Presently your insert statement mentions matric,surname,other,level,bk_id,bk_title columns whereas the columns in select are different. Try like this:
Insert into transaction(matric,surname,other,level,bk_id,bk_title)
values
(select m.matric,m.surname,m.others,m.level,b.isbn,b.bk_title
from member_master m inner join book_master b on m.id = b.id)
Assuming that the two tables are linked with the ID column

Related

How to insert new table value from different database along with its matching id in MYSQL

I have my two MYSQL database:
database 1 with table: Employee with the columns:
Employee_code and
Employee _ID
and database 2 with table: Employee_log with the columns:
Date,
Time and
Employee_ID.
I have now, created a third database 3 with table: Employee_Detailswith the columns:
Employee_code
Employee_ID
Date and
Time.
I have also managed to insert date to the Employee_Details table using the following SQL Query:
INSERT INTO database3.Employee_Details(Employee_ID, Employee_Code)
SELECT Employee_ID, Employee_Code FROM database 1.Employee;
but, now I want to include the Date and Time from database 2 table: Employee_log to the database 3 with the matching employee ID. I tried using the above code but the dates are getting inserted into the table after the Employee_ID in a new row with other column values NULL.
Example:
Employee_ID Employee_Code Date
1 1011
2 1012
Null Null 09/05/2018
Null Null 08/05/2018
So, how can I insert the date to its matching Employee_id, can someone please help me with this.
Thanks,
You could start over by first deleting all rows in database3.Employee_Details.
DELETE FROM database3.Employee_Details;
Next, do an INSERT ... SELECT like you did but join database1.Employee and database2.Employee_log this time.
INSERT INTO database3.Employee_Details
(Employee_ID,
Employee_Code,
Date,
Time)
SELECT Employee.Employee_code,
Employee.Employee_ID,
Employee_log.Date,
Employee_log.Time
FROM database1.Employee
LEFT JOIN database2.Employee_log
ON Employee_log.Employee_ID = Employee.Employee_ID;
In general a join combines the rows of two tables. Each row of the right table is appended to the row of the left table if the condition in the ON clause is true for that pair of rows.
There are some different flavors of joins. Here we use a LEFT JOIN. In a LEFT JOIN the rows of the left table (the table left of the JOIN keyword) are included in the result, even if there were no matching rows from the right table. Instead of the column values from the right table, the respective columns in the result are all null, as there are no values from matching rows.
In contrast a INNER JOIN has only those rows of the left table included where a matching row from the right table exists.
To include all employees, even if no log data was available for them, we had to choose a LEFT JOIN here.
If you don't want to start over, you can update database3.Employee_Details with the missing values.
UPDATE database3.Employee_Details
LEFT JOIN database1.Employee_log
ON Employee_log.Employee_ID = Employee_Details.Employee_ID
SET Employee_Details.Date = Employee_log.Date,
Employee_Details.Time = Employee_log.Time;
Again we use a LEFT JOIN and set the fields in the SET clause with the respective values from the result of the join.
Afterwards delete the unnecessary rows with empty Employee_ID.
DELETE FROM database3.Employee_Details
WHERE Employee_Details.Employee_ID IS NULL;
You can do the insert as:
INSERT INTO database3.Employee_Details(Employee_ID, Employee_Code)
SELECT e.Employee_ID, e.Employee_Code, el.date
FROM database 1.Employee e LEFT JOIN
Employee_log el
ON e.Employee_ID = el.Employee_ID;
You might find it simpler to just create the table as:
CREATE TABLE database3.Employee_Details as
SELECT e.Employee_ID, e.Employee_Code, el.date
FROM database 1.Employee e LEFT JOIN
Employee_log el
ON e.Employee_ID = el.Employee_ID;

Find values missing in a column from a set (mysql)

I am using mysql.
I have a table that has a column id.
Let us say I have an input set of ids. I want to know which all ids are missing in the table.
If the set is "ida", "idb", "idc" and the table only contains "idb", then the returned value should be "ida", "idc".
Is this possible with a single sql query? If not, what is the most efficient way to execute this.
Note that I am not allowed to use stored procedure.
MySQL will only return rows that exist. To return missing rows you must have two tables.
The first table can be temporary (session/connection specific) so that multiple instances can run simultaneously.
create temporary table tmpMustExist (text id);
insert into tmpMustExist select "ida";
insert into tmpMustExist select "idb";
-- etc
select a.id from tmpMustExist as a
left join table b on b.id=a.id
where b.id is null; -- returns results from a table that are missing from b table.
Is this possible with a single sql query?
Well, yes it is. Let me work my way to that, first with a union all to combine the select statements.
create temporary table tmpMustExist (text id);
insert into tmpMustExist select "ida" union all select "idb" union all select "etc...";
select a.id from tmpMustExist as a left join table as b on b.id=a.id where b.id is null;
Note that I use union all which is a bit faster than union because it skips over deduplication.
You can use create table...select. I do this frequently and really like it. (It is a great way to copy a table as well, but it will drop indexes.)
create temporary table tmpMustExist as select "ida" union all select "idb" union all select "etc...";
select a.id from tmpMustExist as a left join table as b on b.id=a.id where b.id is null;
And finally you can use what's called a "derived" table to bring the whole thing into a single, portable select statement.
select a.id from (select "ida" union all select "idb" union all select "etc...") as a left join table as b on b.id=a.id where b.id is null;
Note: the as keyword is optional, but clarifies what I'm doing with a and b. I'm simply creating short names to be used in the join and select field lists
There's a trick. You can either create a table with expected values or you can use union of multiple select for each value.
Then you need to find all the values that are in the etalon, but not in the tested table.
CREATE TABLE IF NOT EXISTS `single` (
`id` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `single` (`id`) VALUES
('idb');
SELECT a.id FROM (
SELECT 'ida' as id
UNION
SELECT 'idb' as id
UNION
SELECT 'idc' AS id
) a WHERE a.id NOT IN (SELECT id FROM single)
//you can pass each set string to query
//pro-grammatically you can put quoted string
//columns must be utf8 collation
select * from
(SELECT 'ida' as col
union
SELECT 'idb' as col
union
SELECT 'idc' as col ) as setresult where col not in (SELECT value FROM `tbl`)

One Row to Match Them All

So I have a situation where I have two tables. One is the base table (called _Keys in this example), with a unique primary key. Then there is another table with multiple rows of a data for each id in _Keys (this second table is Extra).
I need to select the largest value for each primary key in _Keys from Extra. I have made an SQLFiddle to model the problem here.
This is the query I'm currently using, but the issue is that it will only select one value for the Extra table, not one value per row.
Select * from _Keys
LEFT JOIN
(Select * from Extra ORDER BY value2 DESC LIMIT 1) as e
ON e.id = _Keys.id;
For my example SQL Fiddle I used this database schema:
CREATE TABLE _Keys(id int, value int);
INSERT INTO _Keys (id, value) VALUES (1, 5),(2, 3),(3, 4);
CREATE TABLE Extra(id int, value2 int);
INSERT INTO Extra (id, value2) VALUES (1, 3),(1, 1),(2, 4),(2, 6),(3, 3),(3, 5);
Basically my result is here. Only the first row from the _Keys table gets its data from the second table.
In MySQL, how can I achieve selecting one row from Extras for each row in _Keys?
I believe I understand what you are trying to do but I'm not sure.
You are getting NULL values because of the LIMIT, it only returns the first row. You also need to use GROUP BY.
To get the largest value, your can use MAX.
Try this.
SELECT * from _Keys
LEFT JOIN
(SELECT id, MAX(value2) AS value2 FROM Extra GROUP BY id) as e
ON e.id = _Keys.id;
Your joined table Select * from Extra ORDER BY value2 DESC LIMIT 1 will contain only one row because of LIMIT. Try this:
Select * from _Keys
LEFT JOIN
(Select id, max(value2) from Extra group by id) as e
ON e.id = _Keys.id;
You can try this query with better performance :
SELECT k.id, MAX(e.value2) AS value2
FROM _Keys k
INNER JOIN Extra e
ON (k.id = e.id)
GROUP BY k.id;

MySQL Trigger returns multiple rows

I have a MySQL 5.5 Trigger which is failing due to multiple results being returned. The problem is, I'm attempting to return one result at a time by using a unique field 'id' field.
CREATE TRIGGER insert_com_app_title AFTER INSERT
ON com_apps FOR EACH ROW
INSERT IGNORE INTO com_myisam_app_titles(id_company, title) VALUES((SELECT a.id_company, b.title FROM com_apps a JOIN epf_application b ON a.application_id = b.application_id WHERE NEW.id = a.id));
The (relevant) table structure is as follows:
**com_apps**
id, id_company, application_id
**com_myisam_app_titles**
id_company, title
**epf_application**
application_id, title
I'm assuming something is wrong with New.ID, however even if the value is wrong the id field of com_apps is a PRIMARY auto-incremented key, so even in that case I would return one incorrect result.
You shouldn't nest select in a values statement. SQL offers much better syntax:
INSERT IGNORE INTO com_myisam_app_titles(id_company, title)
SELECT a.id_company, b.title
FROM com_apps a JOIN
epf_application b
ON a.application_id = b.application_id
WHERE NEW.id = a.id;
The problem is that the underlying query is returning more than one row and the values statement cannot handle that. The above fixes that problem.
If you only want one row, add a limit 1 to the query:
INSERT IGNORE INTO com_myisam_app_titles(id_company, title)
SELECT a.id_company, b.title
FROM com_apps a JOIN
epf_application b
ON a.application_id = b.application_id
WHERE NEW.id = a.id
LIMIT 1;

Insert into a table with a select statement in mysql

I have a table that has training history that has been modified by many different users over the years. This has cause the same training record to be entered twice. I want to create a table that replicates the main table and insert all duplicate records.
What constitutes a duplicate record is if the employee_id, course_code, and completion_date all match.
I can create the duplicate table and I have a select statement that appears to pull duplicates, but it pulls only one of them and I need it to pull both (or more) of them. This is because one person may have entered the training record with a different course name but the id, code, and date are the same so it is a duplicate entry. So by pulling all the duplicates I can validate that that is the case.
Here is my SELECT statement:
SELECT *
FROM
training_table p1
JOIN
training_table p2 ON (
p1.employee_id = p2.employee_id
AND p1.course_code = p2.course_code
AND p1.completion.date = p2.completion_date)
GROUP BY p1.ssn;
The query runs and returns what appear to be unique rows. I would like all of the duplicates. And whenever I try to INSERT it into an identical table I get an error stating my column count doesn't match my value count.
Any help would be great.
This will select any duplicate rows for insertion into your new table.
SELECT p1.*
FROM training_table p1
JOIN
(SELECT employee_id, course_code, completion_date
FROM training_table
GROUP BY employee_id, course_code, completion_date
HAVING COUNT(*) > 1
) dups
ON p1.employee_id = dups.employee_id
AND p1.course_code = dups.course_code
AND p1.completion_date = dups.completion_date
;
Try to use CROSS JOIN (Cartesian Product Join) instead JOIN only. For insert try INSERT INTO TABLE (column1, column2, column3) SELECT column1, column2, column3 FROM TABLE; in same order.
Thanks for the help. I had discovered the answer shortly after I posted the question (even though I had looked for the answer for over an hour :) ) Here is what I used:
SELECT *
FROM training_table mto
WHERE EXISTS
(
SELECT 1
FROM training_table mti
WHERE mti.employee_id = mto.employee_ie
AND mti.course_code = mto.course_code
AND mti.completion_date = mto.completion_date
LIMIT 1, 1
)
I just added the INSERT statement and it worked.
Thanks.