Unique status where x=y mysql query [closed] - php

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
I'm trying make something unique in my database.
First I check all required rows SELECT * FROM table WHERE x='y'
this gives me 10 rows (as an example). Now what I'm trying to do is UPDATE a field of just one of the 10 rows and disallow any further updates once the update has been executed.
For example, imagine the 10 rows are photos and the WHERE clause is a date. So on a certain date only 10 photos were taken. I have created a field named fave and I want to select just ONE of these images. Basically this is the best photo select on that date.
How do I disable all future updates from this? To prevent me from selecting more than one favourite for any given date?

An unique index can help.
Look at a simple example.
Say we have a table like this:
CREATE TABLE photos(
photo_id int primary key ,
dat date not null,
fave enum ('y')
);
where fave enum ('y') declares, that the column fave can have either 'y' value or NULL.
Then define an unique index on dat+fave columns:
CREATE UNIQUE INDEX only_one_fav ON photos( dat, fave );
The index does allow only one row with given combination of dat+fav, two identic rows are prohibited - however this does not apply to null.
Take a look at this demo: http://www.sqlfiddle.com/#!2/2f28a8/3
CREATE TABLE photos(
photo_id int primary key ,
dat date not null,
fave enum ('y')
);
insert into photos( photo_id, dat ) values
(1,'2013-11-02'),(2,'2013-11-02'),(3,'2013-11-02'),(4,'2013-11-02'),(5,'2013-11-02'),
(11,'2013-11-05'),(12,'2013-11-05'),(13,'2013-11-05'),(14,'2013-11-05'),(15,'2013-11-05');
CREATE UNIQUE INDEX only_one_fav ON photos( dat, fave );
UPDATE photos SET fave = 'y' WHERE photo_id = 2;
UPDATE photos SET fave = 'y' WHERE photo_id =14;
-- UPDATE photos SET fave = 'y' WHERE photo_id = 4;
There are two dates, and 5 photos are taken on each date.
Try to uncommend the last UPDATE command in this demo and hit a Build schema button - you will get an error message - MySql wont allow for two favorite photos id: 2 + 4 on the same date: '2013-11-02'.

Every item in table should have something to differentiate it from the others.... Like an ID.
When you find the one you want to update... Just update on one unique column, or a series of columns that make it unique.

Related

Create a unique ID based on the value in a row for MySQL [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 months ago.
Improve this question
I am in the process of creating a web application for a genealogy project. I want each person I add onto the database to have a unique id, based on the first 3 characters of their surname (let's call it, for the purpose of explaining, 'surname-string'), concatenated with an autoincrement (which starts from 00001 for each unique 'surname-string').
For example - a person's surname is "Smith". The surname-string will be SMI and due to the fact that they are the first surname-string "SMI" the full reference will be SMI00001. Another person's surname is Black, making their surname-string BLA, and because they are the first one with the surname-string BLA, their reference will be BLA00001. A third person's surname is also Smith - they are the second person with the SMI surname-string, so their reference should be SMI00002.
This unique id will be used in the persons URL, to be searched by and create relationships between people in the database.
I have no clue how to approach this logically.
I have not tried anything yet. It goes way over my head!
This method is sketchy, normally you should use auto-increment from database (numeric) or auto generate unique ID, for example md5(time().'randomsalt'.$username).
But if you have to use XXX00000 format you will need function to:
check if there is BLA00001 in database
if yes, check BLA00002 etc.
if no, create new entry
This will be very slow after some time plus every name have maximum 99999 chances of existence, after that you need to change BLA to BL1, BL2 etc.
You can do this using a before insert trigger.
Consider the following table, where uniqu_identifier is the unique identifier based on the surname:
CREATE TABLE test(
id bigint NOT NULL AUTO_INCREMENT,
surname varchar(20),
uniqu_identifier varchar(30) ,
PRIMARY KEY (id)
) ;
You have to use a trigger because MySQL doesn't allow using the auto_increment column on a generated as column.
A trigger would be something like:
CREATE TRIGGER test_BEFORE_INSERT
BEFORE INSERT ON test
FOR EACH ROW
BEGIN
IF EXISTS (SELECT 1 FROM test WHERE left(surname,3) = left(new.surname,3)) THEN
SET new.uniqu_identifier = (select concat(upper(left(new.surname,3)),'0000' ,max(right(uniqu_identifier,1)) +1) from test );
ELSE
SET new.uniqu_identifier = concat(upper(left(new.surname,3)),'00001');
END IF ;
END
Some insert values
insert into test (surname) values ('SMITH');
insert into test (surname) values ('SMITH1');
insert into test (surname) values ('JOHN');
select *
from test;
Result:
id surname uniqu_identifier
1 SMITH SMI00001
2 SMITH1 SMI00002
3 JOHN JOH00001
https://dbfiddle.uk/Wc58Ne_j
Hy
On Create Table you can make the default value of UID like this :
Create Table 'Users'
(ID...
UID varchar(100) Default (CONCAT(SUBSTRING(Firstname, 1, 3), LPAD(ID, 8, '0')))
Substring to return the first 3 char of the username
LPAD to convert the int to 8 digits (ex : 1 => 00000001)

Summarize points in MySQL table by player id in last month and replace with ONE record [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have got a simple game: players earn points, what I store in the POINTS table. I'm afraid the table will be too big, so I want to summarize the points of last month because optimalizing.
For example ID 42 player has got 120 records in the table between 01.08.2019 and 31.08.2019, with 560 points. I would like to delete the 120 rows, and insert only one, with 560 points. I am using PHP(5.6.40) and MySQL.
I have no idea how to solve it. Should I make an archive table, copy the records to it from original table, delete the copied records from original table, and insert back the summarized records only?
POINTS table
id : auto inc. int
timestamp : (unsigned) int
playerid : int
points : tinyint
Do not delete the data from your tables unless there is a very good reason to do so. You want to keep all the data and aggregate it in some other way. What if you make a mistake or a bug and you would like to recalculate the scores?
Generally the SQL aggregate function SUM(score) works really well with indexes and you might have thousands of rows and sum them up on the fly with no perceivable performance reduction.
If you expect a lot of rows in your table you could create an aggregate table and keep the summed up values in it. For example add another column to your players table called total_score and every new record you add for that player in points table will be added to the running total of total_score. You could handle this in your application layer or use DB triggers to update the totals automatically.
You can create a separate table for one maintaining summary of points. Do not delete the master table as it will serve as a point of reference in future if something goes wrong.
Create new table with same structure
CREATE table points_sum LIKE points
Then do one time cleaning to summarize points
INSERT INTO points_sum VALUES (
SELECT id, timestamp, playerid, SUM(points) AS points
FROM points
GROUP BY playerid, FROM_UNIXTIME(timestamp, '%Y-%m')
)
Later all values you store should be summed up before inserting/updating into the table. If player information is not present for the current month, then INSERT else UPDATE. Insert is pretty simple. Here is how you would update it.
UPDATE points_sum
SET points = points + 50
WHERE playerid = '123'
AND timestamp >= UNIX_TIMESTAMP('2018-08-01 00:00:00')
AND timestamp <= UNIX_TIMESTAMP('2018-08-31 23:59:59')

Create timeline from data in different tables [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have a few tables in my script that I need to create a timeline from all of them. The main tables are "posts" - "likes" - "comments".
posts table has rows: PID - UID - title - time_added.
likes table has rows: LID - PID - UID - time_added.
comments table has rows: CID - PID - UID - time_added.
users table has rows: UID - username.
I'm creating a page in the users' profiles called: "Timeline". It should show the actions of the user sorted by time. UID refers to the user ID.
Data example while browsing that page:
User Commented on Post xxxx at xxx_time_added_xxx.
User Liked post xxxx at xxx_time_added_xxx.
User added Post xxxx at xxx_time_added_xxx.
Is there's a way or MySQL query that can combine all these tables and arrange them by time_added?
I thought of creating a new MySQL table: user_timeline that has rows:
TID - UID - PID - LID - CID
And after each action (Post, Like, Comment) and new row is inserted in that table according to the action and add the action ID in the corresponding field and leave the others null. Then call them combined with the related table, if possible.
you can with UNION and aliasing:
select * from ((select 1 as type,time_added from posts where ...) union (select 2 as type,time_added from likes where ...) ...) order by time_added asc
NOTE: Column selection must have the same order in regards to the column type.
Do not do:
(select 1 as type,time_added from posts where ...) union (select time_added,2 as type from likes where ...)
Or if you don`t select the same number of columns in subqueries:
SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns
Your result set will be an multi dimensional array as follows:
array(array('type'=>1,'time_added'=>'...'),array('type'=>2,'time_added'=>'...'));
By TYPE you know if it is a post or a like
Hope this helps

Multiple ID SQL query [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Let's just say I have two tables.
The first one :
id thing1 thing2
The second :
id_fo other_thing
where id_fo depend from the first one table.
I have to insert thingS in both table, but in php mysql request (pdo for example), how can I get all last insert id ?
I mean, if I had 30 row in one query, I will have 30 new id.
How can I do my second SQL query ?
In Psuedo code:
Start transaction
insert into table1 (thing1, thing2) values (thingS,thingS2)
lastidtable1 = lastinsertedid();
insert into table2 (id_fo, other_thing) values (lastidtable1,thingS);
lastidtable2 = lastinsertedId();
commit;
Every of the above lines should php code which calls a query.
Are you looking for something like this ?
$main_data = array('dino', 'babu', 'john');
foreach($main_data as $main) {
// Insert main to 1st table
mysql_query("MY INSERT QUERY TO TABLE 1");
// Get the last insert id
$new_id = mysql_insert_id();
// Insert the sub data to 2nd table using the insert id
mysql_query("MY INSERT QUERY TO TABLE 2 USING $new_id ");
}
INSERT and UPDATE do not return any datasets,you can add an INSERTED column with timestamp type,set DEFAULT to CURRENT_TIMESTAMP and select all rows with the greatest timestamp value.
if you can guarantee that there is only one insert process going on at a time you could do something like this psuedo code:
$max1=select max(id) as max1 from table;
insert into table ....
$num_inserted_rows=number of inserted rows.
$max2=select max(id) as max2 from table;
if(($max2-$max1) == $num_inserted_rows){
$lastid=select last_insert_id();
$inserted_ids=range($lastid-$num_inserted_rows,$lastid);
}

Mysql/sql/zend query with one select? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Well so I got a tiny problem, I got a db and 2 tables like this
Table User
user_id
Table UserrToData
user_id int pk
data_id int
Table UserData
data_id
name
nick
I got the user_id and i need to get records from the userdata , is it possible using 1 query?
Of course, if anyone know how I would really appreciate if he would help me : )
For the selecting I got only the relationship user_id > data_id
update
Guys I got huge db I just simplified the problem to the minimum ^_-
Hope this helps:
SELECT name, nick
FROM UserToData utd INNER JOIN UserData ud ON utd.data_id = ud.data_id
WHERE utd.user_id = [supplied userid]
With such little data, however, there is no need for separate tables, just store name and nick in the User table:
Table User
user_id pk
name
nick
You should overthink your database design. The highest aim is always to prevent redundancies.
If you want the user to have more than one userdata entry you should define your database like this:
Table User
user_id pk
Table UserData
data_id pk
user_id fk
name
nick
So the query would be SELECT * FROM UserData WHERE user_id = ?.
If you only want the user to have one set of userdata you should integrate it into the user table:
Table User
user_id pk
name
nick
So the query would be SELECT * FROM User WHERE user_id = ?.
Why have you put the name and nick in a separate table? You can just put the data in one user table. Might be wise to learn more about how to formulate entities and relations in your database.
Either way, if you ever need to do something like this in Zend at a later time, you can use Zend_Db_Select and do a join. Lookie lookie: http://framework.zend.com/manual/1.12/en/zend.db.select.html#zend.db.select.building.join

Categories