SQL grammar for INSERT SELECT ON DUPLICATE UPDATE - mysql

I want to GROUP and aggregate the rows from one table and insert into the other, and update the aggregate value. What is the SQL command for that?
INSERT INTO tbdetail (detail, views)
(SELECT detail, SUM(views) AS viewsall
FROM tb
GROUP BY detail)
//ON DUPLICATE KEY UPDATE views = views + viewsall <- how to update here?

In MySQL, when using an INSERT ... SELECT statement, you can refer to one of the values of the SELECT statement using the VALUES() function:
INSERT INTO tbdetail (detail, views)
SELECT detail, SUM(views) AS viewsall FROM tb GROUP BY detail
ON DUPLICATE KEY UPDATE views = views + VALUES(views);
More information here: http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_values

Related

laravel export select with insert and update without duplicate

i got this query, i created a table with the fields matricula and kmsTotais. but when i try using a insert and then a update at the end it duplicate rows in the table, how can i make it so that it only updates the rows in the table?
$summaryData = DB::select('SELECT f.matricula, kmsTotais
FROM (
SELECT matricula, SUM(kmfim - quilometragem) AS kmsTotais
FROM formulario
GROUP BY formulario.matricula
) f
I'm trying to make an export of a report, i got raw sql query but i need to insert the query result to a table and update it , making it impossible to duplicate the report result of the query.
but i'm not being able to insert and update in the sql query.

insert into select on duplicate mysql query

I am trying to update on duplicate record in MySQL,
I have a table with many column but i want to update only some column from another table with same desc as current table but it is not updating records.
my query is:
insert into backup_prochart.symbol_list(ticker,end_date,cur_date)
select ticker,t.end_date,t.cur_date from prochart.symbol_list t where
ticker=t.ticker and ticker= 'MAY17' on duplicate key update
end_date=t.end_date,cur_date=t.cur_date;
another query i tried
insert into backup_prochart.symbol_list(ticker,end_date,cur_date) select t.ticker,t.end_date,t.cur_date from prochart.symbol_list t where ticker=t.ticker and t.ticker= 'MAY17' on duplicate key update end_date=t.end_date,cur_date=t.cur_date;
can anyone tell me whats wrong with my query.?
You could try :
INSERT INTO backup_prochart.symbol_list (ticker, end_date, cur_date)
SELECT ticker, end_date, cur_date FROM prochart.symbol_list WHERE ticker = 'MAY17'
ON DUPLICATE KEY UPDATE end_date = values(end_date), cur_date = values(cur_date);
Of course the column "ticker" must be defined as unique for the table "backup_prochart.symbol_list".
You say that you are trying to update a record, but you are using an INSERT statement. Shouldn't you be using UPDATE instead of INSERT?
Difference between INSERT and UPDATE can be found here
Note that you can use UPDATE and SELECT in a single query.
try this. its worked for me.
INSERT INTO employee_projects
(employee_id,
proj_ref_code)
SELECT ep.employee_id,
ep.proj_ref_code
FROM hs_hr_emp_projects_history ep
WHERE NOT EXISTS (SELECT 1
FROM employee_projects p
WHERE ep.employee_id = p.employee_id
AND ep.proj_ref_code = p.proj_ref_code)

How to ignore duplicate keys when extracting data using OPENQUERY while joining two tables?

I am trying to insert records into MySQL database from a MS SQL Server using the "OPENQUERY" but what I am trying to do is ignore the duplicate keys messages. so when the query run into a duplicate then ignore it and keep going.
What ideas can I do to ignore the duplicates?
Here is what I am doing:
pulling records from MySQL using "OpenQuery" to define MySQL "A.record_id"
Joining those records to records in MS SQL Server "with a specific criteria and not direct id" from here I find a new related "B.new_id" record identifier in SQL Server.
I want to insert the found results into a new table in MySQL like so A.record_id, B.new_id Here in the new table I have A.record_id set as a primary key for that table.
The problem is that when joining table A to Table B some times I find 2+ records into table B matching the criteria that I am looking for which causes the value A.record_id to 2+ times in my data set before inserting that into table A which causes the problem. Note I can use aggregate function to eliminate the records.
I don't think there is a specific option. But it is easy enough to do:
insert into oldtable(. . .)
select . . .
from newtable
where not exists (select 1 from oldtable where oldtable.id = newtable.id)
If there is more than one set of unique keys, you can add additional not exists statements.
EDIT:
For the revised problem:
insert into oldtable(. . .)
select . . .
from (select nt.*, row_number() over (partition by id order by (select null)) as seqnum
from newtable nt
) nt
where seqnum = 1 and
not exists (select 1 from oldtable where oldtable.id = nt.id);
The row_number() function assigns a sequential number to each row within a group of rows. The group is defined by the partition by statement. The numbers start at 1 and increment from there. The order by clause says that you don't care about the order. Exactly one row with each id will have a value of 1. Duplicate rows will have a value larger than one. The seqnum = 1 chooses exactly one row per id.
If you are on SQL Server 2008+, you can use MERGE to do an INSERT if row does not exist, or an UPDATE.
Example:
MERGE
INTO dataValue dv
USING tmp_holding_DataValue t
ON t.dateStamp = dv.dateStamp
AND t.itemId = dv.itemId
WHEN NOT MATCHED THEN
INSERT (dateStamp, itemId, value)
VALUES (dateStamp, itemId, value)

Delete statement in a same table

I need to query a delete statement for the same table based on column conditions from the same table for a correlated subquery.
I can't directly run a delete statement and check a condition for the same table in mysql for a correlated subquery.
I want to know whether using temp table will affect mysql's memory/performance?
Any help will be highly appreciated.
Thanks.
You can make mysql do the temp table for you by wrapping your "where" query as an inline from table.
This original query will give you the dreaded "You can't specify target table for update in FROM clause":
DELETE FROM sametable
WHERE id IN (
SELECT id FROM sametable WHERE stuff=true
)
Rewriting it to use inline temp becomes...
DELETE FROM sametable
WHERE id IN (
SELECT implicitTemp.id from (SELECT id FROM sametable WHERE stuff=true) implicitTemp
)
Your question is really not clear, but I would guess you have a correlated subquery and you're having trouble doing a SELECT from the same table that is locked by the DELETE. For instance to delete all but the most recent revision of a document:
DELETE FROM document_revisions d1 WHERE edit_date <
(SELECT MAX(edit_date) FROM document_revisions d2
WHERE d2.document_id = d1.document_id);
This is a problem for MySQL.
Many examples of these types of problems can be solved using MySQL multi-table delete syntax:
DELETE d1 FROM document_revisions d1 JOIN document_revisions d2
ON d1.document_id = d2.document_id AND d1.edit_date < d2.edit_date;
But these solutions are best designed on a case-by-case basis, so if you edit your question and be more specific about the problem you're trying to solve, perhaps we can help you.
In other cases you may be right, using a temp table is the simplest solution.
can't directly run a delete statement and check a condition for the same table
Sure you can. If you want to delete from table1 while checking the condition that col1 = 'somevalue', you could do this:
DELETE
FROM table1
WHERE col1 = 'somevalue'
EDIT
To delete using a correlated subquery, please see the following example:
create table project (id int);
create table emp_project (id int, project_id int);
insert into project values (1);
insert into project values (2);
insert into emp_project values (100, 1);
insert into emp_project values (200, 1);
/* Delete any project record that doesn't have associated emp_project records */
DELETE
FROM project
WHERE NOT EXISTS
(SELECT *
FROM emp_project e
WHERE e.project_id = project.id);
/* project 2 doesn't have any emp_project records, so it was deleted, now
we have 1 project record remaining */
SELECT * FROM project;
Result:
id
1
Create a temp table with the values you want to delete, then join it to the table while deleting. In this example I have a table "Games" with an ID column. I will delete ids greater than 3. I will gather the targets in a temp table first so I can report on them later.
DECLARE #DeletedRows TABLE (ID int)
insert
#DeletedRows
(ID)
select
ID
from
Games
where
ID > 3
DELETE
Games
from
Games g
join
#DeletedRows x
on x.ID = g.ID
I have used group by aggregate with having clause and same table, where the query was like
DELETE
FROM TableName
WHERE id in
(select implicitTable.id
FROM (
SELECT id
FROM `TableName`
GROUP by id
HAVING count(id)>1
) as implicitTable
)
You mean something like:
DELETE FROM table WHERE someColumn = "someValue";
?
This is definitely possible, read about the DELETE syntax in the reference manual.
You can delete from same table. Delete statement is as follows
DELETE FROM table_name
WHERE some_column=some_value

Mysql on duplicate key update + sub query

Using the answer from this question: Need MySQL INSERT - SELECT query for tables with millions of records
new_table
* date
* record_id (pk)
* data_field
INSERT INTO new_table (date,record_id,data_field)
SELECT date, record_id, data_field FROM old_table
ON DUPLICATE KEY UPDATE date=old_table.data, data_field=old_table.data_field;
I need this to work with a group by and join.. so to edit:
INSERT INTO new_table (date,record_id,data_field,value)
SELECT date, record_id, data_field, SUM(other_table.value) as value FROM old_table JOIN other_table USING(record_id) GROUP BY record_id
ON DUPLICATE KEY UPDATE date=old_table.data, data_field=old_table.data_field, value = value;
I can't seem to get the value updated. If I specify old_table.value I get a not defined in field list error.
Per the docs at http://dev.mysql.com/doc/refman/5.0/en/insert-select.html
In the values part of ON DUPLICATE KEY UPDATE, you can refer to columns in other tables, as long as you do not use GROUP BY in the SELECT part. One side effect is that you must qualify nonunique column names in the values part.
So, you cannot use the select query because it has a group by statement. You need to use this trick instead. Basically, this creates a derived table for you to query from. It may not be incredibly efficient, but it works.
INSERT INTO new_table (date,record_id,data_field,value)
SELECT date, record_id, data_field, value
FROM (
SELECT date, record_id, data_field, SUM(other_table.value) as value
FROM old_table
JOIN other_table
USING(record_id)
GROUP BY record_id
) real_query
ON DUPLICATE KEY
UPDATE date=real_query.date, data_field=real_query.data_field, value = real_query.value;
While searching around some more, I found a related question: "MySQL ON DUPLICATE KEY UPDATE with nullable column in unique key".
The answer is that VALUES() can be used to refer to column "value" in the select sub-query.