MySQL one column equal another? - php

How in php/mySQL can i make a column equal another column?
id is auto increment, xid should be unique. Can i make xid = id in SQL? (the reason for this is to log changes but i'll explain more if needed)
To make xid unique the best way is to copy the auto increment of id
+----+-----+----------+----------------+------+---------+
| id | xid | title | body | page | visible |
+----+-----+----------+----------------+------+---------+
| 1 | 1 | my title | my body | NULL | 1 |
| 2 | 2 | my title | my body edited | 1 | 0 |
+----+-----+----------+----------------+------+---------+
$queryX = "INSERT INTO table (xid, title, body, page, visible)
VALUES (, 'Plays', 'it's playing', 'book page', 1)";

I don't understand why you want to do this, but my approach would be using two queries and LAST_INSERT_ID():
INSERT INTO table (title, body, page, visible)
VALUES ('Plays', 'it''s playing', 'book page', 1);
UPDATE table SET xid = id WHERE id = LAST_INSERT_ID();
You may want to do this using a TRIGGER, so you don't have to do it manually.

In one query:
INSERT INTO table (xid, title, body, page, visible) VALUES
( SELECT MAX(xid) + 1, .... )
it will put unique xid, can be done with id also, I not quite sure I undestand the need...

Related

Rewrite of counter by partition

I use mysql and php with phpmyadmin. I have major problem with a partition based counter that I wan't to improve but my knowledge on sql prevents me from doing that. Im struggling very much with this.
I want the duplicated data in my table to have a counter that adds a number after a value if this value gets a duplicated value and then restarts from 1 until a new value is met and so on. Here is what the final result should look like
---------------------------
1 | Josh-1
---------------------------
2 | Josh-2
--------------------------
3 | Josh-3
--------------------------
4 | Josh-4
--------------------------
5 | Fred-1
--------------------------
6 | Fred-2
--------------------------
7 | Fred-3
-------------------------
I had gotten help with this counter here before but it's not working as I wan't it to. Also when I have pressed the insert button in my form the table looks like this in phpmyadmin after I reload it
---------------------------
1 | Josh-1-1-1
---------------------------
2 | Josh-2
--------------------------
3 | Josh-3
--------------------------
4 | Josh-4
--------------------------
5 | Fred-1
--------------------------
6 | Fred-2
--------------------------
7 | Fred
-------------------------
Whats going on here? The code that I seek help with rewriting is this
UPDATE usermeta u1,
(SELECT
u1.`id`, CONCAT(u1.`name`,'-',ROW_NUMBER() OVER(PARTITION BY u1.`name` ORDER BY u1.`id`)) newname
FROM
usermeta u1 JOIN (SELECT `name` , COUNT(*) FROM usermeta GROUP BY `name` HAVING COUNT(*) > 1) u2
ON u1.`name` = u2.`name` ) u3
SET u1.`name` = u3.`newname`
WHERE u1.`id` = u3.`id`
Could this code be rewritten so it creates a table of numbered names and duplicates that looks like the first table example and work like it should in phpmyadmin ? All help is very much appreciated. Keep in mind that I am a struggling moderate sql user.
Possible solution - BEFORE INSERT trigger and additional MyISAM table with secondary autoincrement:
Working table
CREATE TABLE user (id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(127));
Additional table
CREATE TABLE user_index (id INT AUTO_INCREMENT,
name VARCHAR(127),
PRIMARY KEY (name, id)) ENGINE=MyISAM;
Trigger
CREATE TRIGGER insert_user_index
BEFORE INSERT ON user
FOR EACH ROW
BEGIN
DECLARE new_index INT;
INSERT INTO user_index (name) VALUES (NEW.name);
SET new_index = LAST_INSERT_ID();
DELETE FROM user_index WHERE name = NEW.name AND id < new_index;
SET NEW.name = CONCAT_WS('-', NEW.name, new_index);
END
Insert rows - the AI index is added to the name. Check the result.
INSERT INTO user (name) VALUES
('Josh'),
('Josh'),
('Fred'),
('Josh'),
('Fred'),
('Fred'),
('Josh');
SELECT * FROM user;
id | name
-: | :-----
1 | Josh-1
2 | Josh-2
3 | Fred-1
4 | Josh-3
5 | Fred-2
6 | Fred-3
7 | Josh-4
Look what is stored in additional table now.
SELECT * FROM user_index;
id | name
-: | :---
3 | Fred
4 | Josh
db<>fiddle here
If your working table user exists already, and it contains some data, then you'd create additional table and fill it with data using, for example,
CREATE TABLE user_index (id INT AUTO_INCREMENT,
name VARCHAR(127),
PRIMARY KEY (name, id)) ENGINE=MyISAM
SELECT MAX(SUBSTRING_INDEX(name, '-', -1) + 0) id,
SUBSTRING_INDEX(name, '-', 1) name
FROM user
GROUP BY 2;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=38f028cfe1c9e85188ab0454463dcd78

Php MySQL How to Updated/Insert into a database row

Table_A
+--------+-----------+---------+
| id | name | views |
+--------+-----------++--------+
| num | text | int |
+--------+-----------+---------+
| 1 | Video 1 | 10 |
| NULL | NULL | 0 |
| NULL | NULL | 0 |
| NULL | NULL | 0 |
| NULL | NULL | 0 |
+--------+-----------+---------+
<a href="video.php?id=video1&idtitle=Hello%20Video1">
<a href="video.php?id=video2&idtitle=Hello%20Video2">
<a href="video.php?id=video3&idtitle=Hello%20Video3">
I'm trying to make the script do something like this.
1.User click on link
2.User is on video.php?id=video1
3.Mysql then add a +1 to my id column #1
4.then take the video title from $videoName
5.Mysql take the title inside of $videoname and store it on name column #2
6.Mysql then add +1 to Views everytime ID 1 is view
7.Mysql is now finish with Row 1
8.Now Mysql will repeat that same step if video.php?id=video2 and so on,
How can i make this happen?
$id = $_GET['id'];
$videoName = $_GET['idtitle'];
$pdo = new PDO('mysql:localhost;dbname=videocount', 'root', '');
$userip = $_SERVER["REMOTE_ADDR"];
if($userip){
$pdo->query("UPDATE Table_A SET (`id`, `name`, `views`)
VALUES (NULL,$videoName, views+1)");
}
I also try the code below but still no luck.
if($userip){
$pdo->query("INSERT INTO `videocount`.`Table_A` (`id`, `name`, `views`)
VALUES (NULL, '$videoname', 'views'+1)");
}
UPDATE instead of UPDATED, VALUES instead of VALUE. In addition you have to add a WHERE condition to your query to select record to update.
This is another correct syntax:
$pdo->query( "UPDATE `Table_A` SET `views`=`views`+1 WHERE `id`='$id'" );
Edit:
To update also the video name you can perform this query:
$pdo->query( "UPDATE `Table_A` SET `name`='{$videoName}', `views`=`views`+1 WHERE `id`='$id'" );
On the border, you should bind the variable values to avoid errors with titles special characters.
See more about binding and MySQL UPDATE syntax
I think there is a little confusion about data view logic.
First of all, you need to save all data into database, then list them for user.
When the use click the link to view this video, the column of views need to be updated.

Know last X field value

I have a database with this table
+------+---------------------+-------------+
| id | key | value |
+------+---------------------+-------------+
| 152 | incidencia_0_fecha | 20150306 |
| 158 | incidencia_1_fecha | 20150307 |
| 234 | incidencia_2_fecha | 20150309 |
| . | ...... | ........ |
| n | incidencia_N_fecha | date_value |
+------+---------------------+-------------+
And I want to know what is the last key (N its dinamic and i don't know his last value). In this table the last must be incidencia_2_fecha.
How can i do it?
Thanks
You can easily get the number in the string using two REPLACES.
SELECT MAX(
REPLACE(REPLACE(`key`, 'incidencia_', ''), '_fecha', '')
)
FROM mytable
If the values in the id column are strictly increasing, you can do this:
SELECT key FROM your_table WHERE id = (SELECT MAX(id) FROM your_table);
EDIT 1:
If the table is quite large, you should make sure that there's an index on the id column. Otherwise the query could take a long time to run.
EDIT 2:
Another option, if the value column contains the date at the time the record was inserted (and is indexed), would be to do the above query, but replace id with value, i.e.
SELECT key FROM your_table WHERE value = (SELECT MAX(value) FROM your_table);
First fetch record in desc
SELECT key from tbl_name ORDER BY id DESC LIMIT 0,1

SQL optimizing query

I have a table that has the following records:
ID | Username | Selected |
----------------------------
1 | JamesC | 1 |
2 | MikeF | 0 |
3 | JamesC | 0 |
I wish to have Selected be true for only 1 row where the username is the same. So for example when I set ID = 3 to be Selected = true I wish to setID =1 to have Selected = false as well as any other ID's with the same username.
Right now i'm doing this,
//set all to 0
update table set selected = 0 where username = '$username'
//set unique row to true
update table set selected = 1 where username = '$username' and ID = '$ID';
Is there a better more concise way of achieving the same effect?
As it was said - not very nice db structure, it is better to have table with unique names and ID of selected item, anyway, you can go with this single query:
update table set selected=IF(id = '$ID', 1, 0) where username = '$username';
also, try a possible faster variant (test both via explain):
update table set selected=IF(id <> '$ID', 0, 1) where username = '$username';
It looks more like optimizing db structure to me. More info needed for concrete answer though, but check this example to see what I'm talking about:
users:
user_id | user_name | selected_character_id | ...other account data
1 | JamesC | 3
2 | MikeF | 2
characters:
character_id | user_id | ...other character data
1 | 1 |
2 | 2 |
3 | 1 |
You will need JOIN tables to retrieve all data for selected character (fast since it operates on unique ids), but get rid of data duplication (and easier switch).
You will always need the second statement, but as you only have one "Selected" row you could use:
update table set selected = 0 where selected = 1

How to determine order for new item?

I have a members table in MySQL
CREATE TABLE `members` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(65) collate utf8_unicode_ci NOT NULL,
`order` tinyint(3) unsigned NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
And I would like to let users order the members how they like.
I'm storing the order in order column.
I'm wondering how to insert new user to be added to the bottom of the list.
This is what I have today:
$db->query('insert into members VALUES (0, "new member", 0)');
$lastId = $db->lastInsertId();
$maxOrder = $db->fetchAll('select MAX(`order`) max_order FROM members');
$db->query('update members
SET
`order` = ?
WHERE
id = ?',
array(
$maxOrder[0]['max_order'] + 1,
$lastId
));
But that's not really precise while when there are several users adding new members at the same time, it might happen the MAX(order) will return the same values.
How do you handle such cases?
You can do the SELECT as part of the INSERT, such as:
INSERT INTO members SELECT 0, "new member", max(`order`)+1 FROM members;
Keep in mind that you are going to want to have an index on the order column to make the SELECT part optimized.
In addition, you might want to reconsider the tinyint for order, unless you only expect to only have 255 orders ever.
Also order is a reserved word and you will always need to write it as `order`, so you might consider renaming that column as well.
Since you already automatically increment the id for each new member, you can order by id.
I am not sure I understand. If each user wants a different order how will you store individual user preferences in one single field in the "members" table?
Usually you just let users to order based on the natural order of the fields. What is the purpose of the order field?
Usually I make all my select statements order by "order, name"; Then I always insert the same value for Order (either 0 or 9999999 depending on if I want them first or last). Then the user can reorder however they like.
InnoDB supports transactions. Before the insert do a 'begin' statement and when your finished do a commit. See this article for an explanation of transactions in mySql.
What you could do is create a table with keys (member_id,position) that maps to another member_id. Then you can store the ordering in that table separate from the member list itself. (Each member retains their own list ordering, which is what I assume you want...?)
Supposing that you have a member table like this:
+-----------+--------------+
| member_id | name |
+-----------+--------------+
| 1 | John Smith |
| 2 | John Doe |
| 3 | John Johnson |
| 4 | Sue Someone |
+-----------+--------------+
Then, you could have an ordering table like this:
+---------------+----------+-----------------+
| member_id_key | position | member_id_value |
+---------------+----------+-----------------+
| 1 | 1 | 4 |
| 1 | 2 | 1 |
| 1 | 3 | 3 |
| 1 | 4 | 2 |
| 2 | 2 | 1 |
| 2 | 3 | 2 |
+---------------+----------+-----------------+
You can select the member list given the stored order by using an inner join. For example:
SELECT name
FROM members inner join orderings
ON members.member_id = orderings.member_id_value
WHERE orderings.member_id_key = <ID for member you want to lookup>
ORDER BY position;
As an example, the result of running this query for John Smith's list (ie, WHERE member_id_key = 1) would be:
+--------------+
| name |
+--------------+
| Sue Someone |
| John Smith |
| John Johnson |
| John Doe |
+--------------+
You can calculate position for adding to the bottom of the list by adding one to the max position value for a given id.

Categories