A friend of mine wants to check if all the rows, of each of the columns of a table, have the same value.
If they do, then print the value.
Else just print an empty string or null or something.
Imagine this table for example:
+--------+----------+-----+
| Name | Lastname | Age |
+--------+----------+-----+
| Peter | White | 30 |
| Marry | Jane | 30 |
| John | Doe | 30 |
+--------+----------+-----+
The result of the wanted query would output the following:
+--------+----------+-----+
| Name | Lastname | Age |
+--------+----------+-----+
| NULL | NULL | 30 |
+--------+----------+-----+
I tried to create a function where I would get the columns of a given table, loop through each column name and execute a query. But since I am not familiar with Mysql I obviously miss something out and I can't figure out how to achieve what I'm trying to do here.
DROP PROCEDURE IF EXISTS test;
DELIMITER //
create procedure test()
begin
declare i int(11);
declare col_name varchar(50);
declare num_rows int(11);
DECLARE col_names CURSOR FOR
SELECT column_name
FROM information_schema.columns
WHERE table_name='name_of_my_table' and table_schema='name_of_db';
select FOUND_ROWS() as num_rows;
set i = 1;
open col_names;
the_loop: LOOP
IF i > num_rows THEN
CLOSE col_names;
LEAVE the_loop;
END IF;
FETCH col_names
INTO col_name;
-- Here I would like to perform a query for each column
select count(*), col_name from name_of_my_table group by col_name;
-- Then I was thinking of making an if/ else condition to check
-- if I get more than 1 result per column, implying that
-- not all rows have the same value for this column.
SET i = i + 1;
END LOOP the_loop;
CLOSE col_names;
END//
DELIMITER ;
call test;
What this outputs is the count and the column name of the last column found, which does make sense.
I am not sure if what I am trying to do is possible with Mysql only, I can easily do that in PHP but I am wondering if I can do that with a single query as well.
Try the below query.
select if(count(distinct(Name))=1,Name,null), if(count(distinct(Lastname))=1,Lastname,null), if(count(distinct(Age))=1,Age,null)
from your_table;
Related
I am working on a migration project and the data needs to be migrated from system A to system B. The id's in system A and system B will be different. So maintaining a table with source and target column.
As part of the migration, For each record from source A, I need to go to the mapping table to find the corresponding target value. I am just trying avoid querying the mapping table for each query. Is there any way to store the mapping table as a key value map in a stored procedure and query the map as opposed to going to the table directly?
I was searching for collections in MySQL stored procedure, but didn't find anything.
Database A:-
Table : employee
---------------------------------
id | name | email |
---------------------------------
10021 | First1 | first#test.com |
---------------------------------
10035 | First 2| first#test.com |
---------------------------------
Database B:-
Table : employee
---------------------------------
id | name | email |
---------------------------------
1 | First1 | first#test.com |
---------------------------------
2 | First 2| first#test.com |
---------------------------------
Table : emp_mapping
----------------------
source_id | target_id|
----------------------
10021 | 1 |
----------------------
10035 | 2 |
----------------------
Stored Procedure for Migration
DELIMITER //
CREATE PROCEDURE LoadEmployees()
BEGIN
DECLARE db1_empl_id INT;
DECLARE db1_empl_name VARCHAR(20);
DECLARE db1_empl_email VARCHAR(40);
DECLARE db2_empl_id INT;
DECLARE cur CURSOR FOR SELECT id, name, email FROM db1.employees;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET cursor_finished = 1;
open cur;
cur_loop: LOOP
FETCH cur INTO db1_empl_id, db1_empl_name, db1_empl_email;
IF cursor_finished = 1 THEN
LEAVE cur_loop;
END IF;
-- cursor loop statements
-- I would like to move this to a map instead of querying for each record
select target_id into db2_empl_id from db2.emp_mapping where source_id = db1_empl_id;
insert into db2.employee(id,name,email) values(db2_empl_id, db1_empl_name, db1_empl_email);
SET cursor_finished = 0; -- hence reset this value for cursor.
end LOOP;
close cur;
END //
DELIMITER ;
i have a single table with duplicate id.i created a table with distinct id and count of that id i want to compare and update based on that id
+----+-------+
| id | value |
+----+-------+
| 1 | 1:a |
| 1 | 1 |
| 1 | 2:b |
+----+-------+
expected output
+----+-------+
| id | value |
+----+-------+
| 1 | 1:a 1 |
| 1 | 2:b |
+----+-------+
what i have tried is i have written a procedure which executes perfectly but it prematurely exist the loop. i don't know why it exits can anyone guide me
DELIMITER //
CREATE PROCEDURE value_merge()
BEGIN
DECLARE v_val INTEGER DEFAULT 0;
DECLARE i INTEGER DEFAULT 1;
DECLARE row_cou INTEGER DEFAULT 0;
DECLARE colan INTEGER DEFAULT 0;
DECLARE mm_num varchar(20) DEFAULT "";
DECLARE merge_value varchar(132000) DEFAULT "";
DEClARE merge_cursor CURSOR FOR
SELECT Material_Number,cou FROM zz_plant_data_given_table_form_work_bhai where flag='y';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_val = 1;
OPEN merge_cursor;
get_loop: LOOP
FETCH merge_cursor INTO mm_num,row_cou;
IF v_val = 1 THEN
LEAVE get_loop;
END IF;
while i<=row_cou do
SELECT Basic_Data_Text INTO merge_value FROM `zz_plant_data_given_table_form_work` where Material_Number=mm_num and seq=row_cou;
set colan=ROUND ((LENGTH(merge_value)- LENGTH( REPLACE (merge_value, ":", "") )) / LENGTH(":"));
IF colan>0 THEN
set row_cou=row_cou-1;
ELSE
update `zz_plant_data_given_table_form_work` set sts='y' where Material_Number=mm_num and seq=row_cou;
set row_cou=row_cou-1;
update zz_plant_data_given_table_form_work set Basic_Data_Text=concat(Basic_Data_Text,' ',merge_value) where Material_Number=mm_num and seq=row_cou;
END IF;
END while;
update zz_plant_data_given_table_form_work_bhai set flag='' where Material_Number=mm_num;
END LOOP get_loop;
CLOSE merge_cursor;
END//
DELIMITER
;
This two sentences fires the NOT FOUND handler, so I suggest use another type of query to get merge_value
Change it for:
set merge_value = ( SELECT Basic_Data_Text
FROM `zz_plant_data_given_table_form_work`
where Material_Number=mm_num
and seq=row_cou
limit 1 ); /* to prevent errors*/
i want to create a stored procedure by using below requirement.
i tried and written a stored procedure it is working fine with the static values.
how a stored procedure will work with the dynamic values.
Please find my requirement here.
Create a stored proc “skillsparse” that accepts a string of text and and breaks it up into 1,2,3 word phrases.
a. For example: I love java because it’s fun should have these 15 phrases
i. I
ii. I love
iii. I love java
iv. Love
v. Love java
vi. Love java because
vii. Java
viii. Java because
ix. Java because it’s
x. Because
xi. Because it’s
xii. Because it’s fun
xiii. It’s
xiv. It’s fun
xv. fun
3. Store these phrases in a new table called: github_skills_phrases with fields: ID, userid, skills_id (from github_skills_source) and skills_phrase
4. Create a storedproc that compares the skills_phrases against the skills table (ref Table) and store the values into the github_skills table for each user. If possible, please maintain the source of where the skills came from (repodesc, repolang, starred, bio)
5. NOTE: Aside from the info in the new table Kishore is creating, you will also need to run the github_users.bio field against the Skillsparse procedure. You can start this first (for testing logic, etc) since the github_users.bio already exists and has data.
We don’t need to go this for users who have not yet been processed for skills
How i written is:
++++++++++++++++++++++++++++++++++++++++++++++++++++++
DELIMITER $$
CREATE procedure testing(IN id varchar(20),IN usr_id varchar(20),IN str varchar(200))
begin
DECLARE wordCnt varchar(20);
DECLARE wordCnt1 varchar(20);
DECLARE idx INT DEFAULT 1;
DECLARE splt varchar(200);
declare strng varchar(200);
create temporary table tmp.hello1(id varchar(200),usr_id varchar(200),st varchar(200));
set strng = str;
set wordCnt = LENGTH(trim(strng)) - LENGTH(REPLACE(trim(strng), ' ', ''))+1;
set wordCnt1 = LENGTH(trim(strng)) - LENGTH(REPLACE(trim(strng), ' ', ''))+1;
myloop: WHILE idx <= wordCnt DO
set splt = substring_index(trim(strng),' ',idx);
insert into tmp.hello1 values (id,usr_id,splt);
set idx=idx+1;
IF idx = 4 THEN
set strng = substring(trim(strng),length(substring_index(trim(strng),' ',1))+1);
set idx = 1;
set wordCnt = wordCnt -1;
END IF;
end while ;
insert into tmp.hello1 values (id,usr_id,trim(substring(trim(str),length(substring_index(trim(str),' ',wordCnt1-1))+1)));
end $$
Out put ::
mysql> call testing('10','200','I am the my fine the kks hhh nanj kell');
Query OK, 1 row affected (0.77 sec)
mysql> select * from hello1;
+------+--------+---------------+
| id | usr_id | st |
+------+--------+---------------+
| 10 | 200 | I |
| 10 | 200 | I am |
| 10 | 200 | I am the |
| 10 | 200 | am |
| 10 | 200 | am the |
| 10 | 200 | am the my |
| 10 | 200 | the |
| 10 | 200 | the my |
| 10 | 200 | the my fine |
........
..........
| 10 | 200 | kell |
+------+--------+---------------+
27 rows in set (0.00 sec)
my stored procedure is working fine with static values .how to call dynamically a stored procdure by using table data.
Please help me to write a stored procedure to calling with the table data.
If you means you need to call this stored procedure inside select statement on certain data table, this is not available.
You have two options:
1- transfer your procedure to function and then you can call it easily from inside the select statement.
2- write plsql code to call this procedure and you can check the below link about this point
oracle call stored procedure inside select
I was working on a stored procedure to update the order field in a product table.
It works only the problem now is the the last item in the loop(cur), is increased twice instead of once (so dubbeled). Like so:
+-----------------+
|product + order |
|_id | |
| | |
| 1 | 0 |
| 2 | 1 |
| etc.. | etc..|
| 36 | 35 |
| 37 | 36 |
| 38 | 38 |
| |
+-----------------+
I cant figure out why. The link table(CategoryProduct) in this case goes to 38 with a category_id of 2 CALL curorder(2);
Stored procedure:
DELIMITER //
CREATE PROCEDURE curorder(
IN catid INT
)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE i INT DEFAULT 0;
DECLARE p INT;
DECLARE cur CURSOR FOR SELECT product_id FROM test.CategoryProduct WHERE category_id = catid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO p;
UPDATE `test`.`Product` SET `order` = i WHERE `Product`.`product_id` =p;
SET i = i + 1;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE cur;
END //
DELIMITER ;
The Database is a Mysql Database. Any suggestions for improving the procedure are always welcome.
Thanks in advance.
EDIT:
I already tried to place the SET i STATEMENT beneath the IF STATEMENT but with no result.
You should put:
IF done THEN
LEAVE read_loop;
END IF;
Above your update statement, the last time mysql walks trough the loop is uses the old variables because there is no new 'p'. but i is incremented.
I good way to debug stored procedures is with a log table:
CREATE TABLE procedureLog
(
id INTEGER AUTO_INCREMENT,
description TEXT,
PRIMARY KEY (id)
);
For this case you can log the update parameters with the follow query:
INSERT INTO `test`.`procedureLog` (`id` ,`description`) VALUES (null, CONCAT('id: ', CAST(p as CHAR), ' order: ', CAST(i as CHAR)));
Good luck!
I have a MyISAM table comprising over 2 million records, on which there is a FULLTEXT index over multiple columns.
Given a search term, I would like to know how many times it occurs within the indexed fields of each record.
For example, when searching for 'test' within the following table (in which there is a FULLTEXT index over both the FREETEXT and Third_Col columns):
+----+--------------------------------------------+---------------------------+
| ID | FREETEXT | Third_Col |
+----+--------------------------------------------+---------------------------+
| 1 | This is first test string in test example. | This is first test Values |
| 2 | This is second test. | This is sec col |
+----+--------------------------------------------+---------------------------+
I expect results like:
+----+-------+
| ID | count |
+----+-------+
| 1 | 3 |
| 2 | 1 |
+----+-------+
I know that in the FULLTEXT index MySQL uses dtf (the number of times the term appears in the document); how can one obtain this?
Create a user defined function like this
DELIMITER $$
CREATE FUNCTION `getCount`(myStr VARCHAR(1000), myword VARCHAR(100))
RETURNS INT
BEGIN
DECLARE cnt INT DEFAULT 0;
DECLARE result INT DEFAULT 1;
WHILE (result > 0) DO
SET result = INSTR(myStr, myword);
IF(result > 0) THEN
SET cnt = cnt + 1;
SET myStr = SUBSTRING(myStr, result + LENGTH(myword));
END IF;
END WHILE;
RETURN cnt;
END$$
DELIMITER ;
Then you can use this in your query as follows
select id, getCount(concat(FREETEXT, Third_col), 'test') from yourtable
Hope it helps