Update 2nd duplicate value in mysql table? - php

i have 52k rows of records in my user table. In that table user_hash column having approximately 2000 duplicate values. i want to update user_hash columns 2nd duplicate value. The following table user_id (3, 10), (5, 14) having same value and i want to update user_id 10 and 14 values. how can i update it with MySQL Qry?
--------------------------------
user_id user_hash user_status
--------------------------------
1 ae57250b 1
2 310cb4e0 1
3 28b365c7 1
4 0073265b 1
5 8bec42a9 1
6 00a5c443 1
7 e1c27b19 1
8 993dc301 1
9 8fc8a6bf 1
10 28b365c7 1
11 194714c0 1
12 4611d83a 1
13 277a426b 1
14 8bec42a9 1
15 740c1412 1
... ... ...
... ... ...
... ... ...
The following qry which i have used to check duplicate entry
SELECT user_hash, COUNT(user_hash)
FROM user_data
GROUP BY user_hash
HAVING COUNT(user_hash) > 1;

The first thing that comes to mind is that you may want to define a constraint such that in the future you can't have non-unique values where you don't want them.
The second thing is to ensure that these hashes can't legitimately collide/overlap.
Those thoughts aside (as they may be irrelevant to your use case):
update user_data set user_data.user_hash = STORED_PROC_FOR_HASH()
from (
select *, row_number() over(partition by user_hash order by (select null)) row_num
from user_data
) user_data
where row_num > 1
Source for the above query: https://stackoverflow.com/a/25090251/3080207
As hinted at by Nick, you'll need to be able to generate a unique hash, which is pretty much the 2nd component to this problem.
Hopefully that is helpful.

Related

How to update rows with new values for groups found and make this as fast as posible?

I have a table which have these fields: id, client_id, visit_id, number_of_visit.
This table can have from 30k to 100+k rows of data. The primary key is client_id and visit_id. (I cannot have a row with these two values being the same, but meanwhile client_id can appear more than 1 time having different visit_ids and so on).
The thing I want to do is to write values to the field number_of_visit, and this value should be a sequence number of this visit (the first, second, third and so on). I have the visit_id field which is actually a large number, and I need to order it as 'ASC' and write values to number_of_visit accordingly. I have this:
id client_id visit_id number_of_visit
1 103 10 0
2 103 11 0
3 104 12 0
4 105 13 0
5 105 15 0
6 105 16 0
And I want to do this:
id client_id visit_id number_of_visit
1 103 10 1
2 103 11 2
3 104 12 1
4 105 13 1
5 105 15 2
6 105 16 3
I write values to number_of_visit from 1 to n in the same order as visit_id values in ASC order.
This table is able to have more than 1 row with the same client_id, but cannot have a row with the same visit_id, because one visit_id is always relative to a particular client_id. I need to get all the visit_id's of all client_id's in this table, and update the number_of_visit field of these rows with numbers 1, 2, 3, which represent sequence numbers. (if this is the first visit, or it's the second, third and so on ...).
I have this PHP code:
$visit_ids = [];
$sql = "SELECT clientID, GROUP_CONCAT(id) as 'visit_ids' FROM table_report GROUP BY clientID";
$stmt = $pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) {
$visit_ids = explode(',', $row['visit_ids']);
$counter = 1;
foreach ($visit_ids as $id)
{
$query = "UPDATE table_report SET number_of_visit = :value WHERE id = :id";
$statement = $pdo->prepare($query);
$statement->execute([':value' => $counter, ":id" => $id]);
$counter++;
}
}
But the main problem is that it's too slow. The table contains about 40k rows now, but could have more than 100k+. When it's 40k it takes about an hour or two to complete.
What can I do to make this more faster? I have indexes on these fields.
Here's also EXPLAIN output:
Use row_number():
select t.*, row_number() over(partition by client_id order by visit_id) number_of_visit
from table_report t
If you wanted an update statement:
update table_report t
inner join (
select id, row_number() over(partition by client_id order by visit_id) number_of_visit
from table_report t1
) t1 on t1.id = t.id
set t.number_of_visit = t1.number_of_visit

How to fetch all values of a column based on value of another column in same table?

I got the following structure:
admin_id || country_id
---------------------------------
1 2
5 1
1 2
2 3
5 62
1 1
3 62
How to fetch all values by taking the $_SESSION['admin']['id'], finding the country_id of that admin and getting all other admin_id and country_id that are the same of the session admin?
So, lets say the currently logged in admin has id = 5 , that means the admin_id: 5 has two country_id: 1 and 62. I want to take all rows that have country_id: 1 and 62.
It should return this:
admin_id || country_id
------------------------
5 1
5 62
1 1
3 62
How can I do this in one sql query?
You can use a where clause for filtering on the admin_id or the country_id:
select t.*
from t
where t.admin_id = 5 or
t.country_id in (select t2.country_id from t t2 where t2.admin_id = 5);
SELECT t1.*
FROM table t1
JOIN table t2 USING (country_id)
WHERE t2.admin_id = 5
fiddle

Number of 1 time,2 times, 3 times, n times column entries in table in php mysql

Have Table :
id userid type created_date
1 4353535 1 04-06-2014
2 4353536 0 06-06-2014
3 4353537 1 11-06-2014
4 4353538 1 11-06-2014
5 4353539 0 19-06-2014
7 4353541 1 01-06-2014
10 4353544 1 12-06-2014
11 4353535 1 06-06-2014
12 4353536 1 10-06-2014
13 4353537 1 12-06-2014
What I Want : (with in date range)
How much user have single time entry with type 1
How much user have double time entry with type 1
How much user have triple time entry with type 1
How much user have four time entry with type 1
How much user have n time entry with type 1
(PHP & MYSQL)
First get the count for each user, then from that group the entrycount you can get your expected output
select EntryCount, count(userid) from (Select userid, count(id) as Entrycount from myentry group by userid where type=1) as sq group by Entrycount
This will work try
First, get the number of entries per user. Then, get the number of users grouped by number of entries.
SELECT numEntries, COUNT(*) AS numUsers
FROM (
SELECT userid, COUNT(*) AS numEntries
FROM tablename
WHERE type = 1
GROUP BY userid
) tbl
GROUP BY numEntries
Simplified demo
Demo with your data

Select 2-3 number combination from 5 column Table MySQL

Table structure:
MyTable (
ID INT AUTO_INCREMENT,
Num1 INT,
Num2 INT,
Num3 INT,
Num4 INT,
PRIMARY KEY(ID)
)engine=InnoDB;
Now i have around 20-30k records. Num1, Num2, Num3 and Num4 are just some random numbers. Im trying to select 2 and 3 number combinations from this table. For example lets say i have the following rows in table:
ID Num1 Num2 Num3 Num4
1 20 11 9 150
2 30 11 20 19
3 40 45 11 20
I would want to select the most frequently used 2 number combinations and then 3 number combinations. So note that 20 and 11 appear 3 times in table means the combination 20,11 or 11,20 doesnt matter the order has count 3 and so on for other combinations.
I want to retrieve this data in PHP array so that i can do some calculations or display on screen.
What i tried so far:
SELECT *
FROM MyTable
WHERE (Num1 = :num1 AND Num2 = :num2) OR (Num1 = :num1 AND Num3 = :num2) OR
(Num1 = :num1 AND Num4 = :num2) OR (Num2 = :num1 AND Num1 = :num2) OR
(Num2 = :num1 AND Num3 = :num2) OR (Num2 = :num1 AND Num4 = :num2) OR
***
***
and so on for all combinations. Now this gets annoying if i try to use it for 3 number combinations.
Is there a better and efficient way of doing this?
Do i need to restructure table to make this easier?
Will restructured table be normalized? (Right now i think is normalized if not please tell me)
Case 2 combinations
I think you should consider store information in a big matrix like this:
num times_appearing_with_number_1 times_appearing_with_number_2 ...
For a case like
1 8 2 3
1 7 23 24
it would be like:
num 1 2 3 4 5 6 ...
1 - 1 1 0 0 0 ...
2 1 - 1 0 0 0 ...
And then you check which lines have bigger numbers. The indexes would be useful to get the number it corresponds to.
Case 3 combinations
The same with a 3D-matrix.
To feed these tables you should only fetch the information from MySQL and then loop.
since the order of values doesn't matter, there are only 6 permutations to pick two out of four columns (c1-c2, c1-c3, c1-c4, c2-c3, c2-c4 and c3-c4), and only four permutations to pick three (c1-c2-c3, c1-c2-c4, c1-c3-c4, c2-c3-c4).
One approach would be to create a temporary table which contains the id of the row and all 6 (4 for three cols) permutations of those values. You could use a query like this:
SELECT id, CASE Num1<=Num2 WHEN TRUE THEN CONCAT(Num1,"-",Num2) ELSE CONCAT(Num2,"-",Num1) END FROM MyTable
UNION
SELECT id, CASE Num1<=Num3 WHEN TRUE THEN CONCAT(Num1,"-",Num3) ELSE CONCAT(Num3,"-",Num1) END FROM MyTable
...
All that's left then is counting the number of matching rows (note that above query could either be run manually or as a subquery to the counting query)
Edit: Something to fiddle with.

How can I select all the values of a database and choose one of them by a percent

What I want to do is to select a value of the database,
Lets say:
id ---- giftid ---- userid
1 1 481
2 1 422
3 7 123
4 9 542
5 1 122
6 1 455
For example, there are 4 users that want to have the same giftid:
1, 2, 5, 6
It means that each one will have 25% to be chosen.
How can I make the "percent selection"?
Assuming every userid can only claim a giftid once, you can use the ORDER BY RAND() in MySQL. This will firstly select all the rows from table table where the giftid is 1 and then the results are ordered randomly. The LIMIT 1 ensures that only the first record is returned
SELECT * FROM table
WHERE giftid = `1`
ORDER BY RAND()
LIMIT 1
Are you looking this?
SELECT giftid, 1.0 / COUNT(*) percentSelection
FROM tableName
GROUP BY giftid

Categories