mysql insert multi row query result into table - mysql

I came across a scenario where I need to "upgrade" a table with data I obtain from another query. I am adding missing values so I will need to insert, but I cant seem to get it right.
The destination table is the following
CREATE TABLE `documentcounters` (
`UID` int,
`DataChar`,
`SeqNum` ,
`LastSignature`,
`DocumentType`,
`SalesTerminal`,
`Active`,
PRIMARY KEY (`UID`)
) ENGINE=InnoDB
and I am trying to do something like
INSERT INTO documentcounters
SELECT Q1.in_headers, -1,NULL, 17,0,0 FROM
(SELECT DISTINCT(DocumentSeries) as in_headers FROM transactionsheaders )AS Q1
LEFT JOIN
(SELECT DISTINCT(DataChar) as in_counters FROM documentcounters)AS Q2
ON Q1.in_headers=Q2.in_counters WHERE Q2.in_counters IS NULL;
I left UID out because I want the insert statement to create it, but I get a "Column count doesn't match" which makes sense (darn!)
Doing something like
INSERT INTO `documentcounters`
(`DataChar`,`SeqNum`,`LastSignature`,`DocumentType`,`SalesTerminal`,`Active`)
VALUES
(
(SELECT Q1.in_headers FROM
(SELECT DISTINCT(DocumentSeries) as in_headers FROM transactionsheaders )AS Q1
LEFT JOIN
(SELECT DISTINCT(DataChar) as in_counters FROM documentcounters)AS Q2
ON Q1.in_headers=Q2.in_counters WHERE Q2.in_counters IS NULL),-1,NULL,17,0,0
);
yields a "Subquery returns more than 1 row" error.
Any ideas how I can make this work?
Cheers

INSERT INTO `documentcounters`
(`DataChar`,`SeqNum`,`LastSignature`,`DocumentType`,`SalesTerminal`,`Active`)
SELECT Q1.in_headers, -1,NULL, 17,0,0 FROM
(SELECT DISTINCT(DocumentSeries) as in_headers FROM transactionsheaders )AS Q1
LEFT JOIN
(SELECT DISTINCT(DataChar) as in_counters FROM documentcounters)AS Q2
ON Q1.in_headers=Q2.in_counters WHERE Q2.in_counters IS NULL;
This will work if UID is defined as auto_increment.

If you want the INSERT to create the UID values, then UID must be defined as an auto-incrementing column.
CREATE TABLE `documentcounters` (
`UID` INT NOT NULL AUTO_INCREMENT,
...

Related

I want to write a mySQL SELECT query that eliminates rows that have duplicate values in one column

In mySQL
SELECT DISTINCT uID FROM table
returns a recordset with a single uID column where duplicate values are filtered out.
What I'm looking for is something like
SELECT * FROM table (and the uID column is distinct)
that is, where all columns are returned IF the uID value is DISTINCT
edit: here is the full table structure as requested
CREATE TABLE yourTable (
ID int(10) NOT NULL auto_increment,
studyID int(10),
uID varchar(50),
---
PRIMARY KEY (ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
On MySQL 8+, we can use COUNT here as an analytic function:
WITH cte AS (
SELECT *, COUNT(*) OVER (PARTITION BY uID) AS cnt
FROM yourTable
)
SELECT *
FROM cte
WHERE cnt = 1;
On earlier versions of MySQL, we can use exists logic, provided there exist another column which is always unique for each record. Assuming that such an id column exist, we can try:
SELECT *
FROM yourTable t1
WHERE NOT EXISTS (SELECT 1 FROM yourTable t2
WHERE t2.uID = t1.uID AND t2.id <> t1.id);

MySql group by columns and assign them a unique group_id

Basically, there is an abstract task on removing duplicates from db, which linked by it's id with several other tables...
I need to assign for each repeating row in table a unique group_id as max(id) of existing row. Please help
My question in picture
https://i.stack.imgur.com/CVYG1.png
You can group the entities (to find the group ids) at first and then update the group_id of entities.
Example:
UPDATE `t`,
(SELECT `name`, `surname`, MAX(`id`) AS `group_id` FROM `t`
WHERE 1 GROUP BY CONCAT(`name`, `surname`)) AS `t1`
SET `t`.`group_id` = `t1`.`group_id`
WHERE `t`.`name` = `t1`.`name` AND `t`.`surname` = `t1`.`surname`

mySQL DELETE from one table using field from natural joining with another table?

DELETE FROM `takes` WHERE ID, course_ID IN
(SELECT ID, course_ID FROM `takes` natural join `student`
where name = 'Jane' and course_ID='BIOL101')
From the takes table, I am trying to drop all Janes who are enrolled in BIOL101.
The SELECT gives me the correct set of IDs and course_IDs, and I am just trying to DELETE that from the takes table. Having trouble figuring out the proper syntax.
phpMyAdmin gives me the error: "#1093 - You can't specify target table 'takes' for update in FROM clause"
Consider not [ab]using IN, but rather use a proper DELETE..JOIN which MySQL does support.
DELETE takes
FROM takes
JOIN student s
-- The relation/schema is unclear; adapt as required
-- but MAKE SURE A RELATION IS ESTABLISHED!
ON s.student_id = takes.student_id
WHERE s.name = 'Jane'
AND takes.course_ID = 'BIOL101'
Also see this answer.
Try this
DELETE FROM `takes` WHERE (ID, course_ID) IN
(select * FROM(
(SELECT ID, course_ID FROM `takes` natural join `student`
where name = 'Jane' and course_ID='BIOL101')t )
DELETE
FROM `takes`
WHERE `ID` IN
(
SELECT ID FROM `takes`
NATURAL JOIN `student`
WHERE `name` = 'Jane` AND `course_ID` = 'BOIL101'
)

delete duplicate records in mysql

We have 2 tables called : "post" and " post_extra"
summery construction of "post" table's are: id,postdate,title,description
And for post_extra they are: eid,news_id,rating,views
"id" filed in the first table is related to "news_id" to the second table.
There are more than 100,000 records on the table, that many of them are duplicated. I want to keep only one record and remove duplicate records on "post" table that have the same title, and then remove the related record on "post_extra"
I ran this query on phpmyadmin but the server was crashed. And I had to restart it.
DELETE e
FROM Post p1, Post p2, Post_extra e
WHERE p1.postdate > p2.postdate
AND p1.title = p2.title
AND e.news_id = p1.id
How can I do this?
Suppose you have table named as 'tables' in which you have the duplicate records.
Firstly you have to do group by column on which you want to delete duplicate.But I am not doing it with group by.I am writing self join instead of writing nested query or creating temporary table.
SELECT * FROM `names` GROUP BY title, id having count(title) > 1;
This query return number of duplicate records with their title and id.
You don't need to create the temporary table in this case.
To Delete duplicate except one record:
In this table it should have auto increment column. The possible solution that I've just come across:
DELETE t1 FROM tables t1, tables t2 WHERE t1.id > t2.id AND t1.title = t2.title
if you want to keep the row with the lowest auto increment id value OR
DELETE t1 FROM tables t1, tables t2 WHERE t1.id < t2.id AND t1.title = n2.title
if you want to keep the row with the highest auto increment id value.
You can cross check your solution,by selecting the duplicate records again by given query:
SELECT * FROM `tables` GROUP BY title, id having count(title) > 1;
If it return 0 result, then you query is successful.
This will keep entries with the lowest id for each title
DELETE p, e
FROM Post p
left join Post_extra e on e.news_id = p.id
where id not in
(
select * from
(
select min(id)
from post
group by title
) x
)
SQLFiddle demo
You can delete duplicate record by creating a temporary table with unique index on the fields that you need to check for the duplicate value
then issue
Insert IGNORE into select * from TableWithDuplicates
You will get a temporary table without duplicates .
then delete the records from the original table (TableWithDuplicates) by JOIN the tables
Should be something like
CREATE TEMPORARY TABLE `tmp_post` (
`id` INT(10) NULL,
`postDate` DATE NULL,
`title` VARCHAR(50) NULL,
`description` VARCHAR(50) NULL, UNIQUE INDEX `postDate_title_description` (`postDate`, `title`, `description`) );
INSERT IGNORE INTO tmp_post
SELECT id,postDate,title,description
FROM post ;
DELETE post.*
FROM post
LEFT JOIN tmp_post tmp ON tmp.id = post.id
WHERE tmp.id IS NULL ;
Sorry I didn't tested this code

How to prevent GROUP_CONCAT from creating a result when no input data is present?

Given the following MySQL query:
SELECT
`show`.`id`
, GROUP_CONCAT( `showClips`.`clipId` ORDER BY `position` ASC ) AS 'playlist'
FROM
`show`
INNER JOIN
`showClips`
ON
( `show`.`id` = `showClips`.`showId` )
;
I want to retrieve a list of all "shows" from the database, including the ids of contained "clips".
This works fine, as long as there are entries in the show table. For this problem, let's assume all tables are completely empty.
GROUP_CONCAT will return NULL and thus forcing a row into the result (which contains only NULL values).
My application will then think that one show/result exists. But that result will be invalid. This can of course be checked, but I feel like this could (and should) be prevented in the query already.
You should simply add a GROUP BY at the end.
Test case:
CREATE TABLE `show` (id int);
CREATE TABLE `showClips` (clipId int, showId int, position int);
SELECT
`show`.`id`,
GROUP_CONCAT( `showClips`.`clipId` ORDER BY `position` ASC ) AS 'playlist'
FROM `show`
INNER JOIN `showClips` ON ( `show`.`id` = `showClips`.`showId` )
GROUP BY `show`.`id`;
Empty set (0.00 sec)
Add group by show.id, then result will be correct for empty tables:
create table emptyt(id int, name varchar(20));
select id, group_concat(name) from emptyt
result:
NULL, NULL
query with group by
select id, group_concat(name) from emptyt
group by Id
result:
empty dataset