How to set SQL default value equals primary key - mysql

I have a tables called post and look like below:
╔════════════════════════════════════╗
║ post_id origin_post_id rev ║
╠════════════════════════════════════╣
║ 1 1 1 ║
║ 2 1 2 ║
║ 3 3 1 ║
║ 4 3 2 ║
╚════════════════════════════════════╝
post_id is primary key and use auto_increment.
I use origin_post_id to store the origin post id.
I want to set origin_post_id as equal to post_id if it is a new post.
How to let me use
INSERT INTO POST
(POST_ID,
ORIGIN_POST_ID,
REV)
VALUES (NULL,
Default,
3)
What should I do when I create the table?
Is there some ways can get auto_increment key?

Run your above Query
INSERT INTO POST
(POST_ID,
ORIGIN_POST_ID,
REV)
VALUES (NULL,
Default,
3)
then Run update Query
UPDATE POST SET ORIGIN_POST_ID=POST_ID WHERE ORIGIN_POST_ID IS NULL

Related

How to Update a Column Value Start From Left by Using Only a Few Words MySQL

Table Structure
╔════╦════════════════════════════════════════════╗
║ id ║ url ║
╠════╬════════════════════════════════════════════╣
║ 1 ║ http://example.com/path1/path2/path3/name1 ║
╠════╬════════════════════════════════════════════╣
║ 2 ║ http://example.com/path1/path2/path3/name2 ║
╠════╬════════════════════════════════════════════╣
║ 3 ║ http://example.com/path1/path2/path3/name3 ║
╚════╩════════════════════════════════════════════╝
So I'm trying to truncate all url prefixes with that path (ex: http://example.com/path1/path2/path3/) so that there are names left at the end, like: name1, name2, name3.
I think this query can work fine, but I think it will change all the values in that column.
UPDATE `table` SET `url` WHERE LEFT (`url`, 37) = 'http://example.com/path1/path2/path3/'
What I want is to just cut off the front of the url-path leaving the name at the end.
I tried to use this query but the query got an error start from the LEFT after the SET query.
UPDATE `table` SET LEFT(url, 37) = '' WHERE LEFT(`url`, 37) = 'http://example.com/path1/path2/path3/'
How to achieve this?
Use simplest
UPDATE `table`
SET url = TRIM(LEADING 'http://example.com/path1/path2/path3/' FROM url)
If the value starts from the specified substring - it will be trimmed, else the value will not be altered.

MYSQL digit filtering query on text field

I have a database table which looks like this (simplified):
╔════╦══════════════╦═════════╗
║ ID ║ Product ║ Tags ║
╠════╬══════════════╬═════════╣
║ 1 ║ Product1 ║a,1-5,b ║
║ 2 ║ Product2 ║a,6-12,d ║
║ 3 ║ Product3 ║a,20-30,c║
║ 4 ║ Product4 ║b,5-55,a ║
╚════╩══════════════╩═════════╝
The query I'm struggling with should return the results based on Tags column.
Example
Should return all products that have the a tag (no matter of the position determined with , character) with number scope from 6-21 for the second tag, which represents the years of the ones potentially interested into product.
I'm clueless on how to do this.
You should not store multiple values in a string column. It is wrong, wrong, wrong. SQL has a great way to store lists. It is called a table, which has rows and columns for each value.
That said, sometimes we are stuck with other people's really, really, really bad decisions. For those purposes, MySQL has a convenient function, find_in_set():
where find_in_set('a', tags) > 0
Your effort should go into fixing the data model, rather than trying to work around it.

MySQL enforce uniqueness across two columns

I'm trying to achieve something in MySQL that I have not heard is possible before (maybe it is, researching didn't help me much).
What I'm trying to do is enforce uniqueness in MySQL across two columns. What I mean by this is not setting UNIQUE(column1,column2) but the following two conditions:
If a value exists in column1, it cannot be repeated in column1 (same as setting UNIQUE(column1)).
If a value exists in either column, it cannot exist in the other column.
Hence, for the data set {column1,column2}, if {1,2}, {3,4}, {5,6} are data already present, then neither of the two columns can have any of the above data items for new data,i.e. new data item {x,y} where x=NOT{column1} AND y=NOT{column2} AND x!=y
Is this possible? Please help me out here. Thank you.
This might be an overkill, but you can store column1 and column2 in a separate table.
Let's say your table is
create table items (
id int primary key,
column1 int,
column2 int
);
with data:
id | column1 | column2
---|---------|--------
1 | 1 | 2
1 | 3 | 4
1 | 5 | 6
You can change your schema to
create table items (
id int primary key
);
create table item_columns (
item_id int,
position int,
val int,
primary key (item_id, position),
unique key (val),
foreign key (item_id) references items(id)
);
with data:
item_id | position | val
--------|----------|----
1 | 1 | 1
1 | 2 | 2
2 | 1 | 3
2 | 2 | 4
3 | 1 | 5
3 | 2 | 6
You can simulate the old schema with
select i.id, c1.val as column1, c2.val as column2
from items i
left join item_columns c1
on c1.item_id = i.id
and c1.position = 1
left join item_columns c2
on c2.item_id = i.id
and c2.position = 2
You can use it in a view if you like.
Demo: http://rextester.com/PPBT42478
To guaranty the integrity for the position column, you can make it a foreign key to a positions table, which will only contain the values 1 and 2. You could also use ENUM('1', '2'), but ENUM always allow an empty string as a value.

MYSQL query for updating on multiple duplicate field entry

Below is the sample tables I'm working on
Table 1
╔════╦══════════════╦══════╗
║ KID║ REV ║ REDO ║
╠════╬══════════════╬══════╣
║ 1 ║ 43453453345 ║ 2 ║
║ 1 ║ 2433423423 ║ 1 ║
║ 2 ║ 23423423 ║ 1 ║
║ 2 ║ 5566533 ║ 2 ║
╚════╩══════════════╩══════╝
I need to insert REV, KID and REDO into table 1 and while inserting if there is a duplicate entry for both KID and REDO I need to just update REV.
I tried using ON DUPLICATE KEY UPDATE but I have two fields which are not primary here.
How to accomplish that with just plain mysql? Please help me
You could create a trigger which is triggered before an insert and checks if the KID and REDO id already exists. If they exist it executes an update.
The trigger could look for example like this:
delimiter //
CREATE TRIGGER upd_check BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
SET rev = SELECT REV
FROM table1 as t
WHERE t.KID = NEW.KID
AND t.REDO = NEW.REDO;
IF rev != NEW.REV THEN
UPDATE table1
SET REV = NEW.REV
WHERE KID = NEW.KID
AND REDO = NEW.REDO;
END IF;
END;//
delimiter ;
But after the update the insert will still happen thats why you should create
a unique index for the REDO and KID. So if you insert a duplicate you get an error and the trigger will nevertheless update the REV.
CREATE UNIQUE INDEX unique_table1_idx on table1 (KID, REDO)
Another alternative is to send an signal and abort the insert, if the result of the SQL query is not null. Which means the insert will be create an duplicate entry.
signal sqlstate '45000' set message_text = 'duplicate insert';

SQL rank percentile

I've made an SQL query which rank pages by how many times they have been viewed. For instance,
╔══════╦═══════╗
║ PAGE ║ VIEWS ║
╠══════╬═══════╣
║ J ║ 100 ║
║ Q ║ 77 ║
║ 3 ║ 55 ║
║ A ║ 23 ║
║ 2 ║ 6 ║
╚══════╩═══════╝
Now what I would like to do is find the percentile rank of each page using an SQL query. The math I would like to use for this is simple enough, I just want to take the row number of the already generated table divided by the total number of rows. Or 1 minus this value, depending on my interests.
Can I do a COUNT(pages) on an already generated table like this? I realize that's how I will get the total number of rows. But are there any commands to return a row number?
Just to further clarify my question I need the following results
╔══════╦════════════════╗
║ PAGE ║ Percentile ║
╠══════╬════════════════╣
║ J ║ (1-1/5)*100 ║
║ Q ║ (1-2/5)*100 ║
║ 3 ║ (1-3/5)*100 ║
║ A ║ (1-4/5)*100 ║
║ 2 ║ (1-5/5)*100 ║
╚══════╩════════════════╝
Or in general (1-(row number)/(COUNT(page))*100
SELECT page,
views,
(1-ranks/totals)*100 Percentile
FROM
(
SELECT page,
views,
#rank:=#rank + 1 ranks,
(SELECT COUNT(*) FROM tableName) totals
FROM tableName a,
(SELECT #rank:=0) s
ORDER BY views DESC
) s
SQLFiddle Demo
You cannot calculate percentile ranks across a table in a single SQL statement. The approach suggested by John Woo here falls apart after the top ranks are calculated, even though the results do look good for the first (unpredictable) percent of the table being processed, meaning the top few percentiles.
The reason why is explained in this post by Oracle Ace Roland Bouman:
http://rpbouman.blogspot.com/2009/09/mysql-another-ranking-trick.html
In short: user-defined variables are not designed to be reliable within a single SQL statement, only across multiple SQL statements.
Read the first sentence of the MySQL manual about User-Defined Variables:
http://dev.mysql.com/doc/refman/5.5/en/user-variables.html
"You can store a value in a user-defined variable in one statement and then refer to it later in another statement."
Then in about the 10th paragraph see this clear statement: "As a general rule, other than in SET statements, you should never assign a value to a user variable and read the value within the same statement. [. . .] the order of evaluation for expressions involving user variables is undefined. "