Mysql Update / Insert: copying historical data - mysql

I have some historical data tables in my Mysql database.
I want to repeat a day's historical data for another day in the same table.
Table structure, with some sample data:
Id | Date | Value
1 | 2012-04-30 | 5
2 | 2012-04-30 | 10
3 | 2012-04-30 | 15
I want to repeat those ids & values, but for a new date - e.g. 2012-05-01. i.e. adding:
1 | 2012-05-01 | 5
2 | 2012-05-01 | 10
3 | 2012-05-01 | 15
I feel that there should be a straightforward way of doing this... I've tried playing with UPDATE statements with sub-queries and using multiple LEFT JOINs, but haven't get there yet.
Any ideas on how I can do this?
EDIT: To clarify...
- I do NOT want to add these to a new table
- Nor do I want to change the existing records in the table.
- The ids are intentionally duplicated (they are a foreign_key to another table that records what the data refers to...).

INSERT INTO yourTable
SELECT ID, "2012-05-01" As Date, Value
FROM yourTable
WHERE Date = "2012-04-31"
Usually, your ID would be an autoincrement though, so having the same ID in the same table would not work. Either use a different ID, or a different table.
Different ID (next autoincrement):
INSERT INTO yourTable
SELECT NULL as ID, "2012-05-01" As Date, Value
FROM yourTable
WHERE Date = "2012-04-31"
Different table (referring to original ID)
INSERT INTO yourTable_hist
SELECT NULL as ID, ID as old_ID, "2012-05-01" As Date, Value
FROM yourTable
WHERE Date = "2012-04-31"

Maybe something like this:
UPDATE Table1
SET Date=DATE_ADD(Date, INTERVAL 1 DAY)
Or if you want to insert them to a new table:
INSERT INTO Table1
SELECT
ID,
DATE_ADD(Date, INTERVAL 1 DAY),
Value
FROM
Table2

Related

update rate for unique productId by each userID

I'm going to implement a method on my own SQL. I have two tables in MySQL. Suppose that each row is updated in the FirstTable and the values of the rate and countView are variable, I'm trying to update them with the same command:
UPDATE FirstTable SET `countView`= `countView`+1,
`rate`=('$MyRate' + (`countView`-1)*`rate`)/`countView`
WHERE `productId`='$productId'
FirstTable:
productId | countView | rate | other column |
------------+-----------+------+-------------------+---
21 | 12 | 4 | anything |
------------+-----------+------+-------------------+---
22 | 18 | 3 | anything |
------------+-----------+------+-------------------+---
But in this way, a user can vote every time he wants to. So I tried to create a table with two columns productId and userID. Like below:
SecondTable:
productId | userID |
------------+---------------|
21 | 100001 |
------------+---------------|
22 | 100002 |
------------+---------------|
21 | 100001 |
------------+---------------|
21 | 100003 |
------------+---------------|
Now, as in the example given in the SecondTable, a user has given to a productId two vote. So I don't want both of these votes to be recorded.
Problems with this method:
The value of the counter is added to each vote.
I can not properly link the SecondTable and FirstTable to manage the update of the FirstTable.
Of course, this question may not be completely new, but I searched a lot to get the right answer. One of the questions from this site came through this method. Using this method, you can manage the update of a table. This method is as follows:
UPDATE `FirstTable` SET `countView`= `countView`+1,
`rate`=('$MyRate' + (`countView`-1)*`rate`)/`countView`
WHERE `productId`='$productId' IN ( SELECT DISTINCT productId, userID
FROM SecondTable)
But the next problem is that even when I use this command, I encounter the following error:
1241 - Operand should contain 1 column(s)
So thank you so much if you can guide me. And I'm sure my question is not duplicate... thank you again.
This fixes your specific syntax problem:
UPDATE FirstTable
SET countView = countView + 1,
rate = ($MyRate + (countView - 1) * rate) / countView
WHERE productId = $productId AND
productId IN (SELECT t2.productId FROM SecondTable t2);
But if two different users vote on the same product, FirstTable will be updated only once. It is unclear if that is intentional behavior or not.
Note that SELECT DISTINCT is not needed in the subquery.
The error is being generated because you can't return 2 fields in an "in" statement. You'll want to use group by:
Try:
IN ( SELECT DISTINCT productId FROM rating group by product, UserID)
Here's documentation to look over for mysql group by if you want: https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

MySql: Copy sql rows and keep some fields the same while updating others

I have a table with three columns, I want copy/paste all three columns within the same table, however, of the three columns, I want to update two columns with new data specific for that day while keeping one column the same. For the following table:
ticket_number | book_id | log_id
------------- | ------- | ------
1 | 1 | 120
12 | 2 | 120
23 | 3 | 120
I want to:
1) Copy all columns and paste into the same table
2) change the ticket_number column with new data for that day (e.g. 2, 13, 25) as well as the log_id column with the id for the current day (e.g. 121), while keeping book_id column the same.
I have tried with no avail:
INSERT INTO ticket (ticket_number, book_id, log_id) SELECT (2,13,24), (book_id), (121) FROM ticket;
This the schema for reference
Your SELECT query needs to return the rows that you want to insert.
UPDATE: You can use a separate table, which might be easier. Something like this:
CREATE TABLE id_map (
old_ticket_number NUMBER,
new_ticket_number NUMBER
);
You could insert the values into this table.
You can then use this query:
INSERT INTO ticket (ticket_number, book_id, log_id)
SELECT
m.new_ticket_number,
t.book_id,
121
FROM ticket t
INNER JOIN id_map m ON t.ticket_number = m.old_ticket_number;
Does this so what you're looking for?

SQL checking duplicates in one column and deleting another

I need to delete around 300,000 duplicates in my database. I want to check the Card_id column for duplicates, then check for duplicate timestamps. Then delete one copy and keep one. Example:
| Card_id | Time |
| 1234 | 5:30 |
| 1234 | 5:45 |
| 1234 | 5:30 |
| 1234 | 5:45 |
So remaining data would be:
| Card_id | Time |
| 1234 | 5:30 |
| 1234 | 5:45 |
I have tried several different delete statements, and merging into a new table but with no luck.
UPDATE: Got it working!
Alright after many failures I got this to work for DB2.
delete from(
select card_id, time, row_number() over (partition by card_id, time) rn
from card_table) as A
where rn > 1
rn increments when there are duplicates for card_id and time. The duplicated, or second rn, will be deleted.
I strongly suggest you take this approach:
create temporary table tokeep as
select distinct card_id, time
from t;
truncate table t;
insert into t(card_id, time)
select *
from tokeep;
That is, store the data you want. Truncate the table, and then regenerate it. By truncating the table, you get to keep triggers and permissions and other things linked to the table.
This approach should also be faster than deleting many, many duplicates.
If you are going to do that, you ought to insert a proper id as well:
create temporary table tokeep as
select distinct card_id, time
from t;
truncate table t;
alter table t add column id int auto_increment;
insert into t(card_id, time)
select *
from tokeep;
If you haven't Primary key or Candidate key probably there is no option using only one command. Try solution below.
Create table with duplicates
select Card_id,Time
into COPY_YourTable
from YourTable
group by Card_id,Time
having count(1)>1
Remove duplicates using COPY_YourTable
delete from YourTable
where exists
(
select 1
from COPY_YourTable c
where c.Card_id = YourTable.Card_id
and c.Time = YourTable.Time
)
Copy data without duplicates
insert into YourTable
select Card_id,Time
from COPY_YourTabl

MySQL order by date strange prob

I has been working in a updation of a existing website. In that there was a entry form which will save in table... table structure and sample data as follows
id | name | type | in_date | year
-----------------------------------------------------
1 | name1 | 1 | 2-July | 2011
2 | name2 | 2 | 2-June | 2011
3 | name44 | 2 | 8-Sep | 2011
Now I need to order this table in whole date wise ie ( as 2-June-2011) as a simple query
SELECT * FROM order_list order by date DESC
Is any way to do this action ? I tried a lot of query .... Any way to combine these 2 rows ..
We cant alter the DB since it contains more existing records ..
You should store your dates as MySQL DATE types, rather than as strings:
ALTER TABLE order_list ADD COLUMN new_date DATE;
UPDATE order_list
SET new_date = STR_TO_DATE(CONCAT(in_date, '-', year), '%e-%b-%Y');
ALTER TABLE order_list DROP COLUMN in_date, DROP COLUMN year;
Ordering then becomes trivial (i.e. will work exactly as you have attempted):
SELECT * FROM order_list ORDER BY date DESC;
If you're unable to alter the database schema, you can perform the STR_TO_DATE operation in the ORDER BY clause (but this is not very efficient):
SELECT *
FROM order_list
ORDER BY STR_TO_DATE(CONCAT(in_date, '-', year), '%e-%b-%Y') DESC
Don't do that. Put the entire date in one column, and then, if you really have to, create computed columns that will hold the year or day/month.
You can create a simple script that will integrate those two existing columns into the one united-date column in your existing database.
You can try with + (SQL SERVER) or CONCAT (MySQL)
SELECT * FROM order_list order by in_date + year DESC

Reorder rows in a MySQL table

I have a table:
+--------+-------------------+-----------+
| ID | Name | Order |
+--------+-------------------+-----------+
| 1 | John | 1 |
| 2 | Mike | 3 |
| 3 | Daniel | 4 |
| 4 | Lisa | 2 |
| 5 | Joe | 5 |
+--------+-------------------+-----------+
The order can be changed by admin hence the order column. On the admin side I have a form with a select box Insert After: to entries to the database. What query should I use to order+1 after the inserted column.
I want to do this in a such way that keeps server load to a minimum because this table has 1200 rows at present. Is this the correct way to save an order of the table or is there a better way?
Any help appreciated
EDIT:
Here's what I want to do, thanks to itsmatt:
want to reorder row number 1 to be after row 1100, you plan to leave 2-1100 the same and then modify 1 to be 1101 and increment 1101-1200
You need to do this in two steps:
UPDATE MyTable
SET `Order` = `Order` + 1
WHERE `Order` > (SELECT `Order`
FROM MyTable
WHERE ID = <insert-after-id>);
...which will shift the order number of every row further down the list than the person you're inserting after.
Then:
INSERT INTO MyTable (Name, `Order`)
VALUES (Name, (SELECT `Order` + 1 FROM MyTable WHERE ID = <insert-after-id>));
To insert the new row (assuming ID is auto increment), with an order number of one more than the person you're inserting after.
Just add the new row in any normal way and let a later SELECT use ORDER BY to sort. 1200 rows is infinitesimally small by MySQL standards. You really don't have to (and don't want to) keep the physical table sorted. Instead, use keys and indexes to access the table in a way that will give you what you want.
you can
insert into tablename (name, `order`)
values( 'name', select `order`+1 from tablename where name='name')
you can also you id=id_val in your inner select.
Hopefully this is what you're after, the question isn't altogether clear.