Generating another column for table based on values in existing table - mysql

Assuming following table:
CREATE TABLE `item`(
`item_id` int(11) NOT NULL AUTO_INCREMENT,
`item_serial_number` varchar(255) DEFAULT NULL,
`item_type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`item_id`)
)
and following inserts:
INSERT INTO `item` (`item_id`, `item_serial_number`, `item_type`) VALUES
(1, '11232141', 'laptop'),
(2, '22343252', 'printer'),
(3, '34234244', 'printer'),
(4, '78678678', 'charger');
Which SQL commands should I look at/for if I want to add another column, namely item_type_id which will look up on every item_type varchar field value and generate values like this:
------------------------
|ID| SERIAL | TYPE |
------------------------
|1 | 11232141 | laptop |
|2 | 22343252 | printer|
|3 | 34234244 | printer|
|4 | 78678678 | charger|
------------------------
->
----------------------------------
|ID| SERIAL | TYPE | TYPE_ID |
----------------------------------
|1 | 11232141 | laptop | 1 |
|2 | 22343252 | printer| 2 |
|3 | 34234244 | printer| 2 |
|4 | 78678678 | charger| 3 |
----------------------------------

If you want to do this correctly, create a types table:
create table types (
type_id int auto_increment primary key,
type varchar(255)
);
insert into types (type)
select distinct type
from item;
Then, fix your current table:
alter table item add type_id int;
alter table item add constraint fk_types_type_id
foreign key (type_id) references types (type_id);
Then set the value:
update item i join
types t
on i.type = t.type
set i.type_id = t.type_id;
And finally drop the old column:
alter table item drop column type;

Try this-
SELECT item_id AS ID,
item_serial_number AS Serial,
item_type AS Type,
CASE
WHEN item_type = 'laptop' THEN 1
WHEN item_type = 'printer' THEN 2
WHEN item_type = 'charger' THEN 3
END TYPE_ID
FROM `inventory_item_temp`
You can use a lookup table if the list is big. If I guess you have the lookup table as below-
Table Name: Type_id_lookup
item_type type_id
laptop 1
printer 2
charger 3
Mobile 4 -- Sample other item_type
Then the query will be-
SELECT
A.item_id AS ID,
A.item_serial_number AS Serial,
A.item_type AS Type,
B.type_id TYPE_ID
FROM `inventory_item_temp` A
LEFT JOIN `Type_id_lookup` B ON A.item_type = B.item_type

You can use the DENSE_RANK analytical function:
select ID, SERIAL, TYPE,
DENSE_RANK() OVER (ORDER BY SERIAL DESC NULLS LAST) AS TYPE_ID
FROM YOUR_TABLE
But note that, This will give ID 1 to the printer, 2 to laptop and 3 to the charger. but it will be dynamic so no need to give static values in the query.
Cheers!!

Related

Insert statement in self-join table

What is the correct statement to make an insert in a table with a self-join?
If I try to make a classic insert I get the error:
Cannot add or update a child row: a foreign key constraint fails
This is my insert query:
insert into mTable(record_name,self_fk,val, note, ref,insert_date, end_date)
values('processo prova',0,1,'nota di prova', 'az12345', NOW(), NOW());
In your INSERT query, you are referencing to a foreign key (the id 0) that doesn't exist -> constraint fails
I saw in your edits, before you roll it back, your CREATE TABLE script.
The field containing the reference to the parent was created this way :
`id_processo_padre` int(11) NOT NULL DEFAULT '1'
I suggest you to edit this field to make it nullable :
ALTER TABLE `mTable` MODIFY `id_processo_padre` int(11) NULL;
This will allow you to INSERT the first top level parent (or any top level parent)
insert into mTable(record_name, self_fk, ...)
values('processo prova', NULL, ...);
-- ^--^----------This
Test it yourself :
Schema (MySQL v5.7)
CREATE TABLE test
(
id INT(6) NOT NULL PRIMARY KEY AUTO_INCREMENT,
parent_id INT(6) NULL,
someData VARCHAR(255),
FOREIGN KEY (parent_id) REFERENCES test(id)
);
INSERT INTO test VALUES (default, null, "parent"),
(default, 1, "child1_1"),
(default, 1, "child1_2"),
(default, 3, "child2_2");
Query #1
SELECT t1.*, t2.someData AS "My parent's name" FROM test t1
LEFT JOIN test t2
ON t2.id = t1.parent_id
ORDER BY t1.id ASC;
Output
| id | parent_id | someData | My parent's name |
| --- | --------- | -------- | ---------------- |
| 1 | null | parent | null |
| 2 | 1 | child1_1 | parent |
| 3 | 1 | child1_2 | parent |
| 4 | 3 | child2_2 | child1_2 |
View on DB Fiddle

split a field having comma separated values and update the same field by adding additional rows with separated values

I have a field with comma separated values.I want to split the field and add the rows with the obtained values(after splitting) in the same table.
Eg:
**Data as in db**
ID CustomerId Preferences
------------------------------
1. 4456823 AA,BB,DD
2. 4456824 BB,DD
**Data format required**
ID CustomerId Preferences
------------------------------
1. 4456823 AA
2. 4456823 BB
3. 4456823 DD
4. 4456824 BB
5. 4456824 DD
Is there a way I can do this without using a temp table because the the Customer here is a cascading entity..This Id is formed by some other table which is an auto increment key.
Basically I want to update the first field and insert the other split values to get the desired result shown above
Here's one approach using a table of integers (0-9):
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL
,customerid INT NOT NULL
,preferences VARCHAR(100) NOT NULL
);
INSERT INTO my_table VALUES
(1,4456823,'AA,BB,DD'),
(2,4456824,'BB,DD');
DROP TABLE IF EXISTS my_new_table;
CREATE TABLE my_new_table (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,customerid INT NOT NULL,preferences CHAR(2) NOT NULL);
INSERT INTO my_new_table (customerid,preferences)
SELECT DISTINCT customerid, SUBSTRING_INDEX(SUBSTRING_INDEX(preferences,',',i+1),',',-1) x FROM my_table, ints ORDER BY customerid,x;
SELECT * FROM my_new_table;
+----+------------+-------------+
| id | customerid | preferences |
+----+------------+-------------+
| 1 | 4456823 | AA |
| 2 | 4456823 | BB |
| 3 | 4456823 | DD |
| 4 | 4456824 | BB |
| 5 | 4456824 | DD |
+----+------------+-------------+

Mysql query of multiple tables joined

I have the following tables:
machine_machine
id | machineid
1 | EE100034442
item_item
id | upc | name
2 | 10001 | Snickers
machine_setup
id | machine_id | selection | item_id
3 | 1 | A1 | 1
Im trying to get the following output by joining the tables.
machine_setup.machine_id=machine_machine.machineid, machine_setup.selection, item_item.upc, item_item.name
EE100034442 A1 10001 Snickers
Table machine_setup will by the main referenced table as it has multiple selection for each machine_id.
Based on the only id's I can see at the moment to join on, consider this:
create table machine_machine
( id int auto_increment primary key,
machineid varchar(50) not null
);
create table item_item
( id int auto_increment primary key,
upc varchar(30) not null,
name varchar(100) not null
);
create table machine_setup
( id int auto_increment primary key,
machine_id int not null,
selection varchar(30) not null
);
insert machine_machine(machineid) values ('EE100034442');
insert item_item(upc,name) values ('10001','Snickers');
insert machine_setup(machine_id,selection) values (1,'A1'),(1,'A2'),(1,'A(n)');
select mm.machineid,ms.selection,ii.upc,ii.name
from machine_setup ms
join machine_machine mm
on mm.id=ms.machine_id
join item_item ii
on ii.id=ms.machine_id;
+-------------+-----------+-------+----------+
| machineid | selection | upc | name |
+-------------+-----------+-------+----------+
| EE100034442 | A1 | 10001 | Snickers |
| EE100034442 | A2 | 10001 | Snickers |
| EE100034442 | A(n) | 10001 | Snickers |
+-------------+-----------+-------+----------+
I'm not quite sure I understand the question, but the sql you want is like;
Select machine1.machineid, setup.Selection, item.upc, item.name
From Machine_machine machine1 --Set alias for the table
Inner Join machine_setup setup on setup.machine_id = machine1.id --This looks like a link table to me
Inner Join item_item item on setup.item_id = item.id -- in your example this wouldn't link as item_id is 1 in the machine_setup
In your example the machine_setup item_id is set to 1, which means it wouldn't link to the item_item table. i'm assuming this is a mistake.
Let me know if you need more information.

How to implement sequence number database for each group of users?

It's easy to create a database table for storing sequence numbers ; but this design is suited for the event when the sequence is shared for all users. What I want is to create sequence for each group of users : this group can grow at any time because it's a database table , that is the administrator can create a group at any time and users are assigned to a specific group. So how to implement the sequence generation according to a group ?
if you are using myisam
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
Below extracted from above links.
For MyISAM and BDB tables you can specify AUTO_INCREMENT on a
secondary column in a multiple-column index. In this case, the
generated value for the AUTO_INCREMENT column is calculated as
MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is
useful when you want to put data into ordered groups.
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
For your case:
CREATE TABLE mytable (
user_id MEDIUMINT NOT NULL AUTO_INCREMENT,
group_id MEDIUMINT NOT NULL,
user_name CHAR(30) NOT NULL,
PRIMARY KEY (group_id,user_id)
) ENGINE=MyISAM;
INSERT INTO mytable (group_id, user_name) VALUES
(1,'alex'),(1,'jenny'),(2,'baz'),(1,'tim'),(2,'danny'),(3,'joe');
SELECT * FROM mytable ORDER BY group_id,user_id;
Returns:
user_id group_id user_name
1 1 alex
2 1 jenny
3 1 tim
1 2 baz
2 2 danny
1 3 joe

MySQL INSERT if one of primary key value doesn't match

I would like to do MySQL query like this:
if((value1 != dbPrimaryValue1) OR (value2 != dbPrimaryValue2))
INSERT ROW
else
DO NOTHING
Lets try example:
CREATE TABLE `tmp` (
`one` int NOT NULL,
`two` int NOT NULL,
`three` int NOT NULL);
ALTER TABLE `tmp`
ADD PRIMARY KEY (`one`, `two`);
INSERT INTO `tmp`
(`one`, `two`, `three`)
VALUES (1,2,3);
INSERT INTO `tmp`
(`one`,`two`,`three`)
VALUES (10,20,30),
(1,999,999),
(999,2,999),
(1,2,999)
ON DUPLICATE KEY
UPDATE `one` = `one`; // or some dummy no-source-drain operation
Result is here:
select * from tmp;
+-----+-----+-------+
| one | two | three |
+-----+-----+-------+
| 1 | 2 | 3 |
| 10 | 20 | 30 |
| 1 | 999 | 999 |
| 999 | 2 | 999 |
+-----+-----+-------+
U would like to have result like this:
select * from tmp;
+-----+-----+-------+
| one | two | three |
+-----+-----+-------+
| 1 | 2 | 3 |
| 10 | 20 | 30 |
+-----+-----+-------+
Is it possible to make this query? I'm operating with huge data and procedure like load -> compare -> save is not possible. THANKS!
Simply make both fields unique separately. For example:
CREATE TABLE `tmp` (
`one` int NOT NULL UNIQUE,
`two` int NOT NULL UNIQUE,
`three` int NOT NULL);
Or add the constraints via:
ALTER TABLE `tmp` ADD UNIQUE (`one`);
ALTER TABLE `tmp` ADD UNIQUE (`two`);
If you create a UNIQUE key constraint, the database will not allow you to insert them automatically.
From MySQL forum:
A UNIQUE index creates a constraint
such that all values in the index must
be distinct. An error occurs if you
try to add a new row with a key value
that matches an existing row. For all
engines, a UNIQUE index permits
multiple NULL values for columns that
can contain NULL.