Combining multiple rows data into a single row of particular column - mysql

I have a table something like
`
name id date login logout
arjun 1 2012-11-28 9-30 7-30
arjun 1 2012-11-29 9-30 8-00
arjun 1 2012-11-30 9-40 8-00`
i want to view this table as
`
name id date login logout
2012-11-28 9-30 7-30
arjun 1 2012-11-29 9-30 8-00
2012-11-30 9-40 8-00`
Is this possible? if so how?

You can do it with group_concat of mysql
Select
name ,
id ,
group_concat(date) as `Date`,
group_concat(login) as login_time,
group_concat(logout) as logout_time
from mytable
group by name
On the front end you can use loop to display according to your requirements. And if you are using php you can use explode function of php. If something else then try to find out how you can explode the cell value.

Assume your table name is 'table55 '
Then use following query to create stored procedure
delimiter |
create procedure testProcedure()
BEGIN
declare flag1 int default 0;
DECLARE done INT DEFAULT FALSE;
declare tempid int;
declare tempdate date;
declare tempname,templogin,templogout varchar(50);
DECLARE cur1 CURSOR FOR SELECT * from table55 where `name` like 'arjun' and id=1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
drop table if exists mytemptable;
CREATE TEMPORARY TABLE IF NOT EXISTS mytemptable ( `name` VARCHAR(50) NULL DEFAULT NULL,
`id` INT(11) NULL DEFAULT NULL,
`date` DATE NULL DEFAULT NULL,
`login` VARCHAR(50) NULL DEFAULT NULL,
`logout` VARCHAR(50) NULL DEFAULT NULL);
OPEN cur1;
read_loop: LOOP
FETCH cur1 into tempname,tempid,tempdate,templogin,templogout;
if flag1=0 then
insert into mytemptable(name,id,`date`,login,logout) values (tempname,tempid,tempdate,templogin,templogout);
set flag1=1;
else
insert into mytemptable(name,id,`date`,login,logout) values ('',null,tempdate,templogin,templogout);
end if;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
select * from mytemptable;
END
|
delimiter;
You have to run above query only once. After that you can use following query to get required result
call testProcedure

Related

MySQL how to properly check a variable's value from SELECT INTO statement

I have a before insert trigger in a MySQL 8.0 database that checks for the incoming status and passes it along to the stored procedure, which then returns a value to be SET and passed along to be inserted. The stored procedure is being called correctly; however, when checking the entry in the database, the desired value of 1 is expected. However, NULL is there.
Here is the BEFORE_INSERT trigger on the table
CREATE DEFINER=`user`#`` TRIGGER `data_BEFORE_INSERT` BEFORE INSERT ON `data` FOR EACH ROW BEGIN
DECLARE newSearchAddressId INTEGER;
IF NEW.status = 'fresh' THEN
CALL CALC_FRESH_SEARCH_ADDRESS_ID(NEW.lead, #newSearchAddressId);
SET NEW.searchAddressId = #newSearchAddressId;
END IF;
END
Here is what's in the stored procedure:
CREATE DEFINER=`user`#`` PROCEDURE `CALC_FRESH_SEARCH_ADDRESS_ID`(
IN leadId INT,
OUT newSearchAddressId INT
)
proc_label: BEGIN
DECLARE lastSearchAddressID INT;
DECLARE lastStatus VARCHAR(100);
SELECT
`searchAddressId`,
`status`
INTO
lastSearchAddressID,
lastStatus
FROM `leads`
WHERE `id` = leadId;
-- if there is no status previous it's a first time entry
IF lastStatus IS NULL THEN
SET newSearchAddressId = 1;
LEAVE proc_label;
END IF;
END
In the SELECT statement above from leads table I am assured that only one row will be returned.
The desired outcome is that I select those two columns, status and searchAddressId, and if status is NULL, then we know that there is no previous entry and, therefore, a brand new record. Because it is a brand new record, we assign the #newSearchAddressId to the value of 1 and leave the stored procedure early.
I think I am incorrectly setting the variables or checking in the IF statement. That's at least what I think is going on. I have looked at this post and tried setting just one variable to check with an IF statement but the same undesired result of NULL being in the database.
Here is sample data:
DROP TABLE IF EXISTS `data`;
CREATE TABLE `data` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`lead` INT NOT NULL,
`status` VARCHAR(100) NOT NULL,
`searchAddressId INT NOT NULL
) ENGINE=INNODB;
INSERT INTO `data` (`lead`, `status`, `searchAddressId`)
VALUES(1, 'fresh', 1),
VALUES(2, 'suspended', 1),
VALUES(3, 'stale', 1),
VALUES(4, 'fresh', 1),
VALUES(5, 'cancelled', 1);
Based on the data above, here is what I am expecting from the procedure above
DECLARE lastSearchAddressID INT;
DECLARE lastStatus VARCHAR(100);
SELECT `searchAddressId`, `status`
INTO lastSearchAddressID, lastStatus
FROM `data`
WHERE `lead` = 6;
based on the SELECT statement above searchAddressID and lastStatus should be NULL
so when reaching the IF statement of
IF lastStatus IS NULL THEN
SET newSearchAddressId = 1;
LEAVE proc_label;
END IF;
Integer 1 should be assigned to the OUT newSearchAddressId INT in the stored procedure's parameters.
A follow-up query of
SELECT * FROM `data` WHERE `lead` = 6;
Would yield:
id
lead
status
searchAddress
6
6
'fresh'
1
What is yielded:
id
lead
status
searchAddress
6
6
'fresh'
NULL
here is the db fiddle the fiddle is not working but while I fiddle with getting it working I think you can see more clearly the expectations

Dynamic renaming of Columns based on row values in mysql

I am trying to rename columns of a new table based on the row values of a table.
I am using a cursor to fetch the column values corresponding to the old table name. Then altering the newly created table to rename the columns by using the values fetched by the cursor.
The following table shows the columns to be remapped from the client_label to master_label for the respective client_id.
CREATE TABLE `mapping_table` (
`_id` int(11) NOT NULL,
`master_label` varchar(50) DEFAULT NULL,
`client_label` varchar(50) DEFAULT NULL,
`org_label` varchar(50) DEFAULT NULL,
`client_id` varchar(3) DEFAULT NULL
);
INSERT INTO `mapping_table` (`_id`, `master_label`, `client_label`,
`organization_label`, `client_id`) VALUES
(1, 'CUST-ID', 'client', 'TEST', 'tes'),
(8, 'TRANSACTION-ID', 'trno', 'TEST', 'tes'),
(9, 'TRANSACTION-DATE', 'date', 'TEST', 'tes'),
(14, 'PROD-NAME', 'product', 'TEST', 'rbb'),
(16, 'SALES-FIRSTNAME', 'firstname', 'TEST', 'tes')
;
The Procedure looks like this..
BEGIN
DECLARE old_names varchar(50) default null;
DECLARE new_names varchar(50) default null;
DECLARE num_cols varchar(3) DEFAULT null;
DECLARE i INT(3) DEFAULT null;
DECLARE cur_old_names CURSOR for SELECT client_label from`mapping_table` where client_id = ip_client_id order by _id;
DECLARE cur_new_names CURSOR for SELECT master_label from `mapping_table` where client_id = ip_client_id order by _id;
BEGIN
if ip_client_id = (SELECT DISTINCT(client_id) from `mapping_table` where client_id = ip_client_id) THEN
CREATE TABLE `test01`
SELECT * FROM `ROOT_TABLE`;
select count(client_id) into num_cols from `mapping_table` where client_id=ip_client_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- open the cursor
OPEN cur_old_names;
OPEN cur_new_names;
my_loop: LOOP
FETCH NEXT FROM cur_new_names INTO val1;
FETCH NEXT FROM cur_old_names INTO val2;
IF done THEN -- this will be true when we are out of rows to read, so we go to the statement after END LOOP.
LEAVE my_loop;
ELSE
ALTER TABLE `test01 ` change val1 val2 varchar(50);
END IF;
END LOOP;
close cur_old_names;
close cur_new_names;
end if;
END;
END
The test01 table should contain column names from the cursor cur_new_names fetched into val2
While executing, I get the error message,
The following query has failed: "SET #p0='tes'; CALL
`map_column_names`(#p0); "MySQL said: #1054 - Unknown column 'val1' in 'test01_normalized_02'

MySQL optimize comparing function

I'm working on an Android program that introduces in a table approximately 15000 integer values(somewhere between 350-500 lines with 32 columns). In the DB I also have other similar values. This 15000 values that I'm talking about represent a processed image, so basically I want to compare the similarity of two images. Now, when I try to compare the values of two images(I'm comparing value by value and count the equal ones), only the data writing process takes about 7 minutes, which is way too long(I want to be able to write and compare at least 5 images in that time). I know that usually you don't work with this kind of things directly in the DB, but do you think that there is anything that I can do, or is it necessary to do this comparison on the server? The values returned by the descriptor came as line elements separated by ',' and each line is separated by ';'. I take each returned element and save it in a tables column. Here is my code:
Split function:
CREATE DEFINER=`root`#`localhost` FUNCTION `strSplit`(textIn longtext, delim varchar(12), count int) RETURNS int(11)
BEGIN
declare splitString INT(11);
SET splitString = replace(substring(substring_index(textIn, delim, count), length(substring_index(textIn, delim, count - 1)) + 1), delim, '');
RETURN splitString;
END
The function that creates the table:
CREATE TABLE IF NOT EXISTS `myguide`.`objectlocation` (
`ObjectLocationId` INT(11) NOT NULL AUTO_INCREMENT,
`ValueObject` LONGTEXT NOT NULL,
`DescriptorSize` INT(11) NOT NULL,
`DescriptionObject` VARCHAR(45) NOT NULL,
`DataInsert` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`InsertBy` VARCHAR(45) NULL DEFAULT NULL,
PRIMARY KEY (`ObjectLocationId`))
ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARACTER SET = utf8
And this is the code that does the insert part:
CREATE DEFINER=`root`#`localhost` PROCEDURE `myguide_sp_info_imageId`(descriptorIn longtext, sizeDescriptor INT)
BEGIN
declare sizeImagesTable INT DEFAULT (select count(*) from objectLocation);
declare descriptorSizeImage INT;
declare descriptor INT;
declare sizeDescriptorImage INT DEFAULT sizeDescriptor;
declare contorInsertImage INT default 1;
declare descriptorForSplit longtext;
declare descriptorImageSaved longtext;
declare descriptorForSplitImageSaved longtext;
/* check if table exist, drop*/
DROP TEMPORARY TABLE IF EXISTS backupObjectLocation;
/* Create temporar table for store info about objectLocation*/
CREATE TEMPORARY TABLE backupObjectLocation (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
idImage int NOT NULL,
descriptorSaved longtext not null,
sizeDescriptorSaved float not null
);
/* check if table exist, drop*/
DROP TEMPORARY TABLE IF EXISTS processImage;
/* Create temporar table for store info about objectLocation*/
CREATE TEMPORARY TABLE processImage (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
descriptorSaved varchar(255) ,
descriptorReceived varchar(255)
);
SET descriptorImageSaved = RTRIM(descriptorIn);
SET descriptorForSplit = REPLACE(descriptorImageSaved, ';', ',');
INSERT INTO backupObjectLocation (idImage, descriptorSaved, sizeDescriptorSaved)
SELECT ObjectLocationId, ValueObject, DescriptorSize FROM objectLocation;
loop_insertDescriptorImage: LOOP
if contorInsertImage > sizeDescriptorImage then
leave loop_insertDescriptorImage;
end if;
SET descriptor = strSplit(descriptorForSplit, ',', contorInsertImage);
INSERT INTO processImage (descriptorReceived) VALUES (descriptor);
SET contorInsertImage = contorInsertImage + 1;
ITERATE loop_insertDescriptorImage;
end LOOP;
loop_table: LOOP
if sizeImagesTable > 1 then
leave loop_table;
end if;
SET descriptorSizeImage = (SELECT sizeDescriptorSaved from backupObjectLocation where id = sizeImagesTable);
loop_image: LOOP
if descriptorSizeImage > 1 then
leave loop_image;
end if;
SET descriptorImageSaved = (SELECT descriptorSaved from backupObjectLocation where id = sizeImagesTable);
SET descriptorForSplitImageSaved = REPLACE(descriptorImageSaved, ';', ',');
SET descriptorSizeImage = descriptorSizeImage + 1;
ITERATE loop_image;
end LOOP;
SET sizeImagesTable = sizeImagesTable + 1;
ITERATE loop_table;
end LOOP;
select descriptorImageSaved;
select * from backupObjectLocation;
select * from processImage;
END
Please help me find a solution.

Need help writing the case statement - MySQL Cursor

I created two columns in student table for my database. I now need to create a cursor for the student table. I need to make use of the input parameters for start and end student Id’s to filter the results in the cursor query.
I also need to open the cursor created and check if the student has an email assigned or not. If the email is not assigned I need to update the email column to have an email assigned to the student.
Finally to why I want help:
I cannot figure out how I would write the case statements for this cursor. I have tried to think of a good way to do this and not succeeded. Please help!!
DELIMITER $
DROP PROCEDURE IF EXISTS CURSOR_DEMO$
CREATE PROCEDURE CURSOR_DEMO(start_student_id INT
,end_student_id INT
)
BEGIN
DECLARE l_table_name VARCHAR(50);
DECLARE iam_done INT DEFAULT 0;
DECLARE l_sql_stmt VARCHAR(5000);
SET #l_sql_stmt='ALTER TABLE STUDENT ADD EMAIL VARCHAR';
SELECT #l_sql_stmt;
prepare stmt from #l_sql_stmt;
execute stmt;
SET #l_sql_stmt='ALTER TABLE STUDENT ADD PHONE int(10)';
SELECT #l_sql_stmt;
prepare stmt from #l_sql_stmt;
execute stmt;
DECLARE TBL_CUR CURSOR FOR
SELECT EMAIL FROM STUDENT.TABLES WHERE TABLE_SCHEMA='MYSQLDB';
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET IAM_DONE=1;
OPEN TBL_CUR;
tbl_loop:LOOP
FETCH tbl_cur INTO l_table_name;
IF IAM_DONE = 1 THEN
LEAVE tbl_loop;
END IF;
CASE WHEN l_table_name = 'STUDENT' THEN
ELSE BEGIN END;
END CASE;
END LOOP tbl_loop;
CLOSE TBL_CUR;
END;
END$
DELIMITER ;
Is this the kind of thing you need?
/*
drop table student;
delimiter $$
CREATE TABLE `student` (
`id` int(11) NOT NULL ,
`name` char(1) NOT NULL,
`email` varchar(1),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8$$
drop table email;
delimiter $$
CREATE TABLE `email` (
`id` int(11) NOT NULL ,
`type` varchar(8) NOT NULL,
`person_id` int,
`email` varchar(1),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8$$
;
*/
DELIMITER $
DROP PROCEDURE IF EXISTS CURSOR_DEMO$
CREATE PROCEDURE CURSOR_DEMO(start_student_id INT
,end_student_id INT)
BEGIN
declare email_person_id int;
declare email_address varchar(50);
DECLARE done INT DEFAULT 0;
DECLARE CUR CURSOR FOR
SELECT person_id,email FROM sandbox.email where type = 'student';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN CUR;
cur_loop:LOOP
IF done = 1 THEN
LEAVE cur_loop;
END IF;
FETCH CUR INTO email_person_id,email_address;
update student
set email = email_address
where id = email_person_id
and email is null
;
END LOOP cur_loop;
CLOSE CUR;
commit;
END$
DELIMITER ;
truncate table student;
insert into student
values
(1,'A','1'),
(2,'B','1'),
(3,'C',null),
(4,'D',null),
(5,'E',null),
(6,'G',null),
(7,'F',null)
;
truncate table email;
insert into email
values
(1,'student',1,'a'),
(2,'student',2,'b'),
(3,'faculty',7,'z'),
(4,'student',3,'c')
;
select * from student;
call cursor_demo(1,10);
select * from student;

MySQL cursor returns only one record

I'm using Hostgator to host my PHP Website with MySQL 5.5.33 and PHPMyAdmin 3.5.5. I want to use cursor to get values from individual record in a table. The followings is the code for that stored procedure:
CREATE DEFINER=`lnutri`#`localhost` PROCEDURE `TestCursor`()
NO SQL
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE cGroupID INT;
DECLARE cGroupName VARCHAR(50);
DECLARE cursor1 CURSOR FOR SELECT GroupID, GroupName FROM Groups;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor1;
read_loop: LOOP
FETCH cursor1 INTO cGroupID,cGroupName;
IF done THEN
LEAVE read_loop;
END IF;
SELECT cGroupID AS GroupID, cGroupName as GroupName;
END LOOP;
CLOSE cursor1;
END
But the stored procedure seems to return the first record only:
GroupID GroupName
1 Default Group
This is the structure of the Groups table
CREATE TABLE IF NOT EXISTS `Groups` (
`GroupID` int(11) NOT NULL AUTO_INCREMENT,
`GroupName` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`Description` varchar(500) COLLATE utf8_unicode_ci NOT NULL,
`DateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`GroupID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=39 ;
And this is the Groups Table's data:
GroupID GroupName Description DateCreated
1 Default Group 0000-00-00 00:00:00
2 Group 2 0000-00-00 00:00:00
29 Regis 0000-00-00 00:00:00
31 Benetas 0000-00-00 00:00:00
32 Domain 0000-00-00 00:00:00
36 none 0000-00-00 00:00:00
37 Aevum 2013-11-11 17:40:56
38 Uniting Aged Care 2013-11-15 07:26:19
Your problem is that the stored procedure returns as many resultset as you have rows in your table and every resultset has only one row. Your client, which happens to be phpmyAdmin, doesn't process multiple resultsets. Thats why you see only one row.
To check that your cursor works just fine all you need is to temporarily create table (let's call it log) and then change
SELECT cGroupID AS GroupID, cGroupName as GroupName;
to
INSERT INTO log(group_id, group_name)
SELECT cGroupID AS GroupID, cGroupName as GroupName;
And you'll see that you after you call your procedure you'll have all your records in log table.
Here is SQLFiddle demo
Now it's absolutely impractical to do what you just did. If you really need to do some processing on a row by row basis and the return some results then
create a temporary table
inserted needed results in it while you iterate over the cursor
return the resultsest from the temp table to the client using select
drop the temporary table
To illustrate this let's say you want your procedure to return only every other row. Then your procedure might look like this
DELIMITER $$
CREATE PROCEDURE `TestCursor`()
BEGIN
DECLARE done, counter INT DEFAULT FALSE;
DECLARE cGroupID INT;
DECLARE cGroupName VARCHAR(50);
DECLARE cursor1 CURSOR FOR SELECT GroupID, GroupName FROM Groups;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CREATE TEMPORARY TABLE log
(
id int not null auto_increment primary key,
group_id int,
group_name varchar(50)
);
OPEN cursor1;
read_loop: LOOP
FETCH cursor1 INTO cGroupID,cGroupName;
SET counter = counter + 1;
IF done THEN
LEAVE read_loop;
END IF;
IF counter % 2 <> 0 THEN
INSERT INTO log(group_id, group_name)
SELECT cGroupID AS GroupID, cGroupName as GroupName;
END IF;
END LOOP;
CLOSE cursor1;
SELECT * FROM log;
DROP TABLE log;
END
DELIMITER ;
Here is SQLFiddle