I have a database , where table contains consecutive duplicate rows . Demo of table with data is as follows.
id name processed
1 xyz 0
2 xyz 0
3 ABC 0
4 ABC 0
I want to delete the consecutive duplicate from this table , and once duplicate is deleted update processed to 1. So that the final table looks like follows.
id name processed
1 xyz 1
3 ABC 1
I am doing it as follow.
SET #v1 := (select group_concat(`id`) from `names` as m1 where 0 < (select count(*) from `names` as m2 where m2.`id` = m1.`id` - 1 and m2.`name` = m1.`name`));
DELETE FROM names WHERE id IN (#v1);
UPDATE names SET `processed`=1 WHERE `processed`=0
The query works fine , but it deletes one row at a time . Please help me on this.I want all the selected rows to be deleted .
Thanks in advance.
As #MarkBaker already wrote in comment, you can try DELETE FROM table WHERE name=name and id>id.
But that's only fix to what already has been done. To prevent that, you should add unique index to name column. That should prevent any duplicates of being added in future.
You can't set unique index when you have duplicates though, so you need clean first :)
You cannot UPDATE and DELETE in the same query. So that pretty much leaves you with this:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,name CHAR(3) NOT NULL,processed TINYINT NOT NULL DEFAULT 0);
INSERT INTO my_table VALUES
(1 ,'xyz', 0),
(2 ,'xyz', 0),
(3 ,'ABC', 0),
(4 ,'ABC', 0);
SELECT * FROM my_Table;
+----+------+-----------+
| id | name | processed |
+----+------+-----------+
| 1 | xyz | 0 |
| 2 | xyz | 0 |
| 3 | ABC | 0 |
| 4 | ABC | 0 |
+----+------+-----------+
SELECT y.* FROM my_table x JOIN my_table y ON y.id = x.id + 1 AND y.name = x.name;
+----+------+-----------+
| id | name | processed |
+----+------+-----------+
| 2 | xyz | 0 |
| 4 | ABC | 0 |
+----+------+-----------+
DELETE y FROM my_table x JOIN my_table y ON y.id = x.id + 1 AND y.name = x.name;
Query OK, 2 rows affected (0.00 sec)
UPDATE my_table SET processed = 1;
Query OK, 2 rows affected (0.00 sec)
SELECT * FROM my_table;
+----+------+-----------+
| id | name | processed |
+----+------+-----------+
| 1 | xyz | 1 |
| 3 | ABC | 1 |
+----+------+-----------+
For PHP and MySQL, If your all data is consecutive pairs then this will work.
$con = mysqli_connect('host', 'user', 'pass', 'db');
$query ="select m1.id from names as m1 where 0 < (select count(*) from names as m2 where m2.id = m1.id - 1 and m2.name = m1.name)";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_array($result)){
$query2 ="DELETE FROM names WHERE id = ".$row['id'];
mysqli_query($con, $query2);
$id = $row['id']-1;
$query3 ="UPDATE names SET `processed`=1 WHERE id = ".$id;
mysqli_query($con, $query3);
}
I checked it and its working fine. Hope it works for you too.
This will not edit your table, but will give you SELECT with desired result:
SELECT min(id) id, name, 1 processed
FROM mytable
GROUP BY name
You can use this in CREATE TABLE newtable AS SELECT ..., and then DROP mytable, and finally to ALTER TABLE newtable RENAME TO mytable.
The DISTINCT keyword can be used to return only distinct (different) values.
Use this query:
SELECT DISTINCT `id`, `name`,`1` AS processed
FROM mytable;
Related
I have this query:
SELECT * FROM `date1` UNION SELECT * FROM `date2` ORDER BY (count1+count2) DESC
I need exclude duplicate entries by 'ID' column.
Can I do this with UNION?
Update:
table1
+---------+--------+
| id | count1 |
+---------+--------+
| 112337 | 567 |
+----+-------------+
table2
+---------+--------+
| id | count1 |
+---------+--------+
| 112337 | 565 |
+----+-------------+
I want to display only first 'id' data.
You can use NOT EXISTS:
SELECT * FROM date1
UNION
SELECT d2.* FROM date2 d2
WHERE NOT EXISTS (SELECT 1 FROM date1 d1 WHERE d1.id = d2.id)
Also change to UNION ALL, which is more efficient, if you don't want to exclude duplicate rows or if there re no duplicate ids in each table.
Using a union and wrapping it in a main query with aggregation may be what you want.
DROP TABLE IF EXISTS T,T1;
CREATE TABLE T(ID INT, COUNT1 INT);
CREATE TABLE T1(ID INT, COUNT1 INT);
INSERT INTO T VALUES (1,567),(2,20);
INSERT INTO T1 VALUES(1,565),(3,20);
select tid ,
max(case when tcount1 is not null then tcount1 else t1count1 end) cnt
from
(select id tid,count1 tcount1,null t1count1 from t
union
select id tid,null tcount1,count1 from t1
) s
group by tid;
+------+------+
| tid | cnt |
+------+------+
| 1 | 567 |
| 2 | 20 |
| 3 | 20 |
+------+------+
3 rows in set (0.001 sec)
I am facing a strange issue using mysqli table. I have table in which there are some records. I am executing following query
SELECT * FROM `users` WHERE
EXISTS (
SELECT *
FROM `games`
INNER JOIN `users_games`
ON `games`.`id` = `users_games`.`game_id`
WHERE
`users`.`id` = `users_games`.`user_id` AND `game_id` = 10
)
AND `users`.`id` = 10
LIMIT 12;
In users_games table there are 11 rows (1 to 13) for user_id = 10. The above query is working for all
`game_id` = 10 /* it is working */
When I try to execute game_id= 1 then it is not showing record however there is row for game_id= 1.
Below it users_games table
Given these users
select id from users;
+-----+
| id |
+-----+
| 1 |
| 2 |
| 3 |
| 6 |
| 7 |
| 8 |
| 10 |
| 12 |
| 14 |
| 15 |
| 16 |
| 17 |
| 999 |
+-----+
and this
drop table if exists games,users_games;
create table games (id int);
create table users_games(user_id int, game_id int);
insert into games values (1),(10);
insert into users_games values(1,1),(1,10),(10,1);
Your query
SELECT id FROM `users` WHERE
EXISTS (
SELECT *
FROM `games`
INNER JOIN `users_games`
ON `games`.`id` = `users_games`.`game_id`
WHERE
`users`.`id` = `users_games`.`user_id` AND `game_id` = 1
)
AND `users`.`id` = 10;
Produces
+----+
| id |
+----+
| 10 |
+----+
1 row in set (0.00 sec)
Which is as expected. You could improve your question by including sample data as text in the question (as I have done in the answer).
In a table myTable defined as:
+----+---------+-----------+
| id | name | value |
|----+---------+-----------+
| 7 | hand | right |
| 5 | hand | left |
| 0 | hand | both |
| 0 | feet | both |
| 0 | eyes | green |
| 9 | eyes | blue |
| 2 | eyes | white |
| 2 | hand | raised |
+----+---------+-----------+
Default settings are controlled by id = 0.
My question is how to write a select statement to get name,value for id = 5 in one query that will include set for id = 5 and any defaults not overridden.
The results should be:
+---------+-----------+
| name | value |
+---------+-----------+
| hand | left |
| feet | both |
| eyes | green |
+---------+-----------+
It isn't clarified if the ordering of the result set is important, so might as well try:
SELECT name,
value
FROM MyTable
WHERE id = 5
AND id NOT IN
(
SELECT id
FROM MyTable
WHERE id = 0
GROUP BY MyTable.id
)
UNION
SELECT name,
value
FROM MyTable
WHERE id = 0
AND name NOT IN
(
SELECT name
FROM MyTable
WHERE id = 5
GROUP BY MyTable.name
)
Disclaimer: Tested in SQL Server, but not using anything specific to that version of SQL.
seems this one may work for you:
SELECT id,name,value
FROM test
WHERE id = 5
UNION
SELECT id,name,value
FROM test
WHERE id=0
and name not in (select name from test where id=5)
The following does not return three rows in the result set, it only returns a single row with columns hand, feet and eyes, so it may not work for you. But it should return the data that you're looking for given your conditions:
SELECT (CASE
WHEN EXISTS(SELECT 1 FROM myTable WHERE name='hand' AND id=5)
THEN (SELECT `value` FROM myTable WHERE name='hand' AND id=5)
ELSE (SELECT `value` FROM myTable WHERE name='hand' AND id=0)
END) AS hand,
(CASE
WHEN EXISTS(SELECT 1 FROM myTable WHERE name='feet' AND id=5)
THEN (SELECT `value` FROM myTable WHERE name='feet' AND id=5)
ELSE (SELECT `value` FROM myTable WHERE name='feet' AND id=0)
END) AS feet,
(CASE
WHEN EXISTS(SELECT 1 FROM myTable WHERE name='eyes' AND id=5)
THEN (SELECT `value` FROM myTable WHERE name='eyes' AND id=5)
ELSE (SELECT `value` FROM myTable WHERE name='eyes' AND id=0)
END) AS eyes
;
Output:
+---------+-----------+-----------+
| hand | feet | eyes |
+---------+-----------+-----------+
| left | both | green |
+---------+-----------+-----------+
This is approach generates 10 different SELECT statements rather than 1, and the accepted answer is, for most applications, probably a better way to go about it.
SELECT * FROM mytable WHERE ID = 5
UNION
SELECT * FROM mytable WHERE ID = 0 AND name NOT IN (SELECT name FROM MyTable
WHERE id = 5)
Should get you the right answer.
http://sqlfiddle.com/#!9/1f516/14
I'm back again. Been searching and trying this for hours... Haven't found an answer or even the right question.
I want to fix a crashed table that I recreated from memory (and the members list in Works) using an query in phpMyAdmin. I need to populate each members total posts.
forum_messages
member_id | message |
--------------------
1 | Hello |
3 | One, Two, Three |
1 | Howdy! |
2 | Here we are again! |
2 | To answer your question... |
forum_members
member_id | posts |
--------------------
1 | 0 |
2 | 0 |
From forum_messages, forum_members should end up looking like this:
forum_members
member_id | posts |
--------------------
1 | 2 |
2 | 2 |
3 | 1 |
Thanks!
Using an INSERT SELECT query, you should be able to rebuild the data you had lost in the forum_members table.
This would return the number of messages per member_id:
SELECT member_id, COUNT(*) FROM forum_messages GROUP BY member_id;
Collating it with an INSERT query puts it into the table instead of displaying the data as it normally would in an SELECT query.
INSERT INTO forum_members (member_id, posts) SELECT member_id, COUNT(*) FROM forum_messages GROUP BY member_id;
try this :
UPDATE forum_members SET posts = (SELECT COUNT(*) FROM forum_messages where forum_messages.member_id = forum_members.member_id GROUP BY forum_messages.member_id)
I think you need just to count messages by members, isn't it?
If so, use this SQL:
TRUNCATE TABLE forum_members;
INSERT INTO forum_members(member_id, posts)
SELECT member_id, COUNT(1) FROM forum_messages GROUP BY member_id;
This should fix it.. Please note that the code is NOT TESTED. You should echo the outcome of the update query to check if it's correct before executing the update query
$get_memberid = "SELECT distinct(member_id) as member_id FROM forum_members;";
$Rget_memberid = mysql_query($get_memberid) or die(mysql_error());
while($row_get_memberid = mysql_fetch_array($Rget_memberid)) {
$arr_get_memberid[] = array( "member_id" => $row_get_memberid['member_id'] );
}
for ($c = 0; $c < count($arr_get_memberid); $c++){
$update_count = "UPDATE forum_members set posts = (SELECT count(member_id) from forum_messages where member_id = '".$arr_get_memberid[$c]['member_id']."') where member_id = '".$arr_get_memberid[$c]['member_id']."';";
$Rupdate_count = mysql_query($update_count) or die(mysql_error());
}
Hi I have a MySQL database table "points" the user can click a button and a point should be removed from their account, the button they pressed has an ID of another user, therefore their account must increase by one.
I have it working in jQuery and checked the varibles/posts in Firebug, and it does send the correct data, such as:
userid= 1
posterid = 4
I think the problem is with my PHP page:
<?php
include ('../functions.php');
$userid=mysql_real_escape_string($_POST['user_id']);
$posterid=mysql_real_escape_string($_POST['poster_id']);
if (loggedin())
{
include ('../connection.php');
$query1 = "UPDATE `points` SET `points` = `points` - 1 WHERE `userID` = '$userid'";
$result1=mysql_query($query1);
$query2 = "UPDATE `points` SET `points` = `points` + 1 WHERE `userID` = '$posterid'";
$result2=mysql_query($query2);
if ($result1 && result2)
{
echo "Successful";
return 1;
}
else
{
echo mysql_error();
return 0;
}
}
?>
Any ideas? Thanks :)
Two queries to increase/decrease field value are not necessary:
UPDATE table SET field = field + 1 WHERE id = 1
is a perfectly valid query as you can see next:
mysql> describe points;
+--------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| uid | int(11) | NO | PRI | NULL | |
| points | int(11) | YES | | 0 | |
+--------+---------+------+-----+---------+-------+
2 rows in set (0.05 sec)
mysql> insert into points VALUES (1,0),(2,0);
Query OK, 2 rows affected (0.14 sec)
mysql> select * from points;
+-----+--------+
| uid | points |
+-----+--------+
| 1 | 0 |
| 2 | 0 |
+-----+--------+
2 rows in set (0.05 sec)
mysql> update points set points = points+1 where uid = 1;
Query OK, 1 row affected (0.27 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from points;
+-----+--------+
| uid | points |
+-----+--------+
| 1 | 1 |
| 2 | 0 |
+-----+--------+
2 rows in set (0.00 sec)
Having that tested, are you sure you get into your if (loggedin()) clause?
I have to agree with KM, would be nice to see output of echo $query1; or echo $query2;
Here is the example query, tested by me and it is working 100%
$query="UPDATE table_name SET `hit_count`=(`hit_count`+1) WHERE `id` = '1'";
update table_name set col_name=col_name+1 where sqId = 12
But if your col_name by default value is null or empty it never works, so make sure that col_name default value is 0 or any integer value.
update 'tablename' set 'columnname1'='columnname1' + 1 where 'columnname2'='value';
eg: update students set englishmarks=englishmarks + 1 where name='Rahul';
Edit:(Explanation)
"UPDATE" keyword is used to update a vaule in the table. Here I am updating a value in the table "students". "SET" keyword updating the english marks by 1(just like in C language, how we increase the value of an integer, i=i+1) and condidtion is given where name is "Rahul".
So englishmarks of Rahul are incremented by 1
In laravel Migration do:
\DB::statement('SELECT #pos:=0;');
\DB::statement('UPDATE users SET company_id = ( SELECT #pos := #pos + 1 ) WHERE `id` = '1';');
If want to change all records, remove the WHERE id = '1'
It will insert number increment to your records like:
+-----+------------+
| id | company_id |
+-----+------------+
| 1 | 1 |
| 12 | 2 |
| 23 | 3 |
+-----+------------+