Reputation: 1509
I have a table with an auto increment key id
, item_no
can be either one or two rows in a row (so they always have consecutive id
s) that share the same ref
but have different right/left
(but technically item_no
can be repeated multiple times throughout the table but that's not an issue), and description
will sometimes be the same on the consecutive rows but sometimes different:
id | item_no | description | right\left | ref
1 | 1 | a1 | right | aaa
2 | 1 | a1 | left | aaa
3 | 2 | b1 | right | bbb
4 | 3 | c1 | right | ccc
5 | 3 | c2 | left | ccc
6 | 4 | d1 | right | ddd
7 | 4 | d1 | left | ddd
My issue is that I need item_no
to append a -r or -l on to its value if the description
of its 'matching' row is different.
So the result I am looking for is:
id | item_no | description | right\left | ref
1 | 1 | a1 | right | aaa
2 | 1 | a1 | left | aaa
3 | 2 | b1 | right | bbb
4 | 3-r | c1 | right | ccc
5 | 3-l | c2 | left | ccc
6 | 4 | d1 | right | ddd
7 | 4 | d1 | left | ddd
I am exporting the table to a csv but am not using much php, just a mysql statement and then looping out the results, is this possible within the mysql statement or will I have to rely on a php loop?
Upvotes: 2
Views: 921
Reputation: 5833
I would rely on a PHP loop if you're using mysql, if you were using Oracle or SQL server then you could program a stored procedure.
You script should look something like this:
$dbh = new PDO('mysql:host='.DATABASE_HOST.';dbname='.DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$data = $dbh->query("SELECT * FROM ExampleTable");
$dbh->beginTransaction();
foreach($data as $row)
{
$append = $row["right\left"] == "left" ? $row["item_no"]."-l" : $row["item_no"]."-r";
$stmnt = $dbh->prepare("UPDATE ExampleTable SET item_no = :item WHERE id = :id");
$stmnt->execute(array(":item" => $append,":id" => $row["id"]));
}
// Do some exception handling if something goes wrong you can allways do a rollback
// With PDO $dbh->rollBack();
$dbh->commit();
$dbh = null;
Upvotes: 1
Reputation: 49089
I would use this:
update
items inner join
(select item_no from items
group by item_no
having count(distinct description)>1) dup
on items.item_no=dup.item_no
set
items.item_no=concat(items.item_no, '-', substr(rightleft, 1,1))
If rows are always consecutive, you could also use this:
update
items i1 inner join items i2
on (i1.id=i2.id+1 or i1.id=i2.id-1)
and (i1.item_no=i2.item_no)
and (i1.description<>i2.description)
set i1.item_no=concat(i1.item_no, '-', substr(i1.rightleft, 1,1))
EDIT: if rows are always consecutive, and you just need a select and not an update, you could use this:
select
i1.id,
case when i1.description=i2.description or i2.id is null then i1.item_no else
concat(i1.item_no, '-', substr(i1.rightleft, 1,1)) end,
i1.description, i1.rightleft, i1.ref
from
items i1 left join items i2
on (i1.id=i2.id+1 or i1.id=i2.id-1) and (i1.item_no=i2.item_no)
order by i1.id
Upvotes: 2
Reputation: 79979
Try this:
SELECT
id,
CASE RightLeft
WHEN 'right' THEN CONCAT(item_no, '-r' )
WHEN 'left' THEN CONCAT(item_no, '-l' )
END AS item_no,
DESCRIPTION,
Rightleft,
ref
FROM Items
WHERE item_no IN
(
SELECT i1.item_no
FROM items i1
GROUP BY i1.item_no
HAVING(COUNT(DISTINCT description)) > 1);
This will give you:
| ID | ITEM_NO | DESCRIPTION | RIGHTLEFT | REF |
------------------------------------------------
| 4 | 3-r | c1 | right | ccc |
| 5 | 3-l | c2 | left | ccc |
Upvotes: 1
Reputation: 3979
Something like this
UPDATE [dbo].[maTable] SET [item_no] = [item_no]+'r' WHERE not distinct [description] from [dbo].[maTable]
Should add an 'r' in the registration line where [description] is not identical (coded for SQL Server)
Upvotes: 0