Upsert In MySql without ON DUPLICATE KEY (single query without procedure) - mysql

I have two table A, B. Where A is master table B is stage table. Many stage table get created B(for different state[AP, MH, UP, TN..] by updates provided by these states) exist and need to upsert in table A Monthly.
A- Id(Primery Key), Name, Email, ContactNumber, State, TimeStamp, Active(True, False)
A contains all data from each states, with last update date as time stamp and With flags.
B- Name, Email, ContactNumber
For now B is is considered to be updates from state AP. And contains updates means, B can have some row deleted which was earlier and some added and can have few same Previous rows.
I have to upsert by joning(on name, email, contact_number) all the updates for AP in such way,
IF row only present in A then Active_flag is False
IF row present in both then UPDATE row in A as timestamp=now() and active_flag=True
If row present in B insert into A with extra values STATE=AP and timestamp=now() and active=True
Is it possible using CASE, or IF-ELSE (Will it be fast instead of using multiple query like first update and insert)?

It seems you are looking for a REPLACE INTO command, as described in MySQL manual with mysql's select syntax (insert into sometable select * from anothertable), like this:
replace into mastertable m
select
field1, field2, field3, now()
from
stagetable s
outer join
mastertable m2 on m2.id=s.id
where
m2.ActiveFlag=true or m2.ActiveFlag is null
Of course I didnt try this, but this would be the general idea.

Related

Insert multiple records into a table based on AVG values from another table in mySQL

I have a mysql database with 2 tables. The first "spec" is a specification table, the second 'log' is table containing logged entries of previous measurements. Each part being logged is identified by a part number and test measurement. There may be many log entries for any given part number, but only 1 entry per part number in the 'spec' database giving the actual specification. What I need to do is obtain an average of the test measurement for every different part in the 'log' table, and insert this into the 'spec' table as a new specification. The log table will have already have been corrected to remove outliers.
I have been able to update existing records in the 'spec' table, but have been unable to insert records that do not already exist.
This works
update no_flow.spec s join
(select part, round(avg(cc),0) as avgcc
from no_flow.log l
group by part) l
on s.part = l.part and l.avgcc > 0
set s.cc = l.avgcc;
This does not work
INSERT INTO no_flow.spec set (part, cc) s join
SELECT part, avg(cc)
FROM no_flow.log l
WHERE id != 0
values (l.part, l.avgcc);
Suggestions?
If there is a unique index on part in spec you could use INSERT ... ON DUPLICATE KEY UPDATE Syntax
It would look something like this:
INSERT INTO noflow.spec (part, cc)
select
part as logPart,
round(avg(cc),0) as avgcc
from
no_flow.log
group
by logPart
ON DUPLICATE KEY UPDATE cc = VALUES(cc);
This inserts all the records from the inner SELECT into the spec table. When a given inserted record encounters a duplicate key error (i.e. there is already a record for the current part number) the ON DUPLICATE KEY clause updates the existing record by setting its cc column equal to the cc column on the record it was trying to insert.

Can't add date to archive

I have duplicated a Table to create an Archive table, and for some reason I can't make to Appending Query to work.
This is the SQL code:
INSERT INTO tblArc
SELECT tblCostumer.*
FROM tblCostumer, tblArc
WHERE (((tblArc.num)=[Enter Client Number you'd like to move to the archive]));
When I enter the costumer number, it says "You are about to append 0 row(s)" instead of appending 1 row.
That FROM clause would give you a cross join, which is probably not what you should really want ...
FROM tblCostumer, tblArc
Instead SELECT only from tblCostumer based on its primary key. For example, if the primary key is tblCostumer.num ...
INSERT INTO tblArc
SELECT tblCostumer.*
FROM tblCostumer
WHERE tblCostumer.num=[Enter Client Number you'd like to move to the archive];
And if the structures of the two tables are not the same, list the specific fields instead of ...
INSERT INTO tblArc
SELECT tblCostumer.*

Deleting duplicates in mysql (2 tables)

I have two tables (id_test, test) , each of them has an ID column, which is unique, and two entries with the same id in the two tables are the same. Now, i have another column in one of the tables (id_test) that also should be unique, so I want to eliminate duplicates according to this other column, let's call it YD.
To identify the duplicates I used
SELECT ID, YD AS x, COUNT(*) AS y
FROM id_test
GROUP BY x
HAVING y>1;
now, I want to delete these entries in both tables. How can I do it?
This query shows the first ID for every YD in id_test table:
SELECT ID, YD
FROM id_test
GROUP BY YD
and these are the rows you have to keep. The following query returns the IDs you have to delete:
SELECT id_test.ID
FROM id_test LEFT JOIN (select ID, YD from id_test group by YD) id_test_keep
on id_test.ID=id_test_keep.ID and id_test.YD = id_test_keep.YD
WHERE id_test_keep.ID IS NULL
Now I think i need more details about your tables, but what I think you need is this:
DELETE FROM test
WHERE
test.ID IN (
SELECT id_test.ID
FROM id_test LEFT JOIN (select ID, YD from id_test group by YD) id_test_keep
on id_test.ID=id_test_keep.ID and id_test.YD = id_test_keep.YD
WHERE id_test_keep.ID IS NULL)
As documented under ALTER TABLE Syntax (emphasis added):
IGNORE is a MySQL extension to standard SQL. It controls how ALTER TABLE works if there are duplicates on unique keys in the new table or if warnings occur when strict mode is enabled. If IGNORE is not specified, the copy is aborted and rolled back if duplicate-key errors occur. If IGNORE is specified, only the first row is used of rows with duplicates on a unique key. The other conflicting rows are deleted. Incorrect values are truncated to the closest matching acceptable value.
Therefore:
ALTER IGNORE TABLE id_test ADD UNIQUE (YD)
I think you don't user select in because if data large it impossible.
You should clone a table the same structure. Insert data not duplicate in it.
INSERT INTO test_new (ID, YD) SELECT t.ID, t.YD FROM test t LEFT JOIN test_id ti ON t.ID = ti.id WHERE ti.id IS NULL;
After drop table test, rename test_new -> test.

MSQL creating a table which automatically updates with data from other tables

I have two tables:
Table1 - Sales
id, Timestamp, Notes, CSR, Date, ExistingCustomer, PubCode, Price, Pub, Expiry, Size, KeyCode, UpSell, CustName, CustAddress, CustCity, CustState, CustPostal, CustCountry, CustPhone, CustEmail, CustCardName, CustCardNumber, CustCardType, CustCardExpiry, CustCardCode
Table2 - Refunds
id,Timestamp,CSR,Date,OrderId,Refunded,Saved,Publication
Basically, I want to create a table (MySQL) which will have some columns that are the same between the two tables and which will update automatically with the values from these two columns.
ie. Table3
Timestamp, CSR, Date, Publication
And this table would automatically update whenever a new record is posted into either of the other two tables, so it would essentially be a merged table.
Because there's nothing to join these two tables, I don't think the JOIN function would work here. Is there anyway I can do this?
You can use an trigger which actives on insert on both tables to make it automatically update.
As for combining tables with no common tables, view this question.
You need to use a stored procedure and a trigger on insert/update of the non merged table
There's got to be some way to join it, and in fact you mention Timestamp, CSR, Date, Publication.
You could join on them in a view. You could add table three and then add triggers though that would be an awful mess.
Why do you want to denormalise in this way?
How about Table3 is a unique key to use as a surrogate, and your 4 join fields, and then you take those out of Table 1 and 2 and replace them with the key the suurrogate key in table 3.
Then it'sa simple join query and no data duplication.

Fix DB duplicate entries (MySQL bug)

I'm using MySQL 4.1. Some tables have duplicates entries that go against the constraints.
When I try to group rows, MySQL doesn't recognise the rows as being similar.
Example:
Table A has a column "Name" with the Unique proprety.
The table contains one row with the name 'Hach?' and one row with the same name but a square at the end instead of the '?' (which I can't reproduce in this textfield)
A "Group by" on these 2 rows return 2 separate rows
This cause several problems including the fact that I can't export and reimport the database. On reimporting an error mentions that a Insert has failed because it violates a constraint.
In theory I could try to import, wait for the first error, fix the import script and the original DB, and repeat. In pratice, that would take forever.
Is there a way to list all the anomalies or force the database to recheck constraints (and list all the values/rows that go against them) ?
I can supply the .MYD file if it can be helpful.
To list all the anomalies:
SELECT name, count(*) FROM TableA GROUP BY name HAVING count(*) > 1;
There are a few ways to tackle deleting the dups and your path will depend heavily on the number of dups you have.
See this SO question for ways of removing those from your table.
Here is the solution I provided there:
-- Setup for example
create table people (fname varchar(10), lname varchar(10));
insert into people values ('Bob', 'Newhart');
insert into people values ('Bob', 'Newhart');
insert into people values ('Bill', 'Cosby');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Adam', 'Sandler');
-- Show table with duplicates
select * from people;
-- Create table with one version of each duplicate record
create table dups as
select distinct fname, lname, count(*)
from people group by fname, lname
having count(*) > 1;
-- Delete all matching duplicate records
delete people from people inner join dups
on people.fname = dups.fname AND
people.lname = dups.lname;
-- Insert single record of each dup back into table
insert into people select fname, lname from dups;
-- Show Fixed table
select * from people;
Create a new table, select all rows and group by the unique key (in the example column name) and insert in the new table.
To find out what is that character, do the following query:
SELECT HEX(Name) FROM TableName WHERE Name LIKE 'Hach%'
You will se the ascii code of that 'square'.
If that character is 'x', you could update like this:(but if that column is Unique you will have some errors)
UPDATE TableName SET Name=TRIM(TRAILING 'x' FROM Name);
I'll assume this is a MySQL 4.1 random bug. Somes values are just changing on their own for no particular reason even if they violates some MySQL constraints. MySQL is simply ignoring those violations.
To solve my problem, I will write a prog that tries to resinsert every line of data in the same table (to be precise : another table with the same caracteristics) and log every instance of failures.
I will leave the incident open for a while in case someone gets the same problem and someone else finds a more practical solution.