How can I change SELECT statement to IF statement in Mysql? - mysql

In mysql, I tried to print '-1' if 3 conditions are satisfied.
SELECT '-1'
WHERE not exists(select * from acq_staff where acq_person_id = staffID)
OR not exists(select * from acq_training_course_session where training_course_id = course_id)
OR exists(select * from acq_training_enrolment where acq_staff_acq_person_id = staffID);
But how can I change this SELECT statement to IF statement so that if either those 3 conditions are satisfied, print -1 otherwise I am going to insert a data.
Sorry for not enough information

MySQL INNER JOIN, along with WHERE NOT EXISTS, can be used to determine if there's an existing course, and existing staff, and that staff is enrolled in that course, and if not, INSERT the staff and course id in the enrollment table.
-- create
CREATE TABLE acq_staff (
acq_person_id INTEGER PRIMARY KEY
);
CREATE TABLE acq_training_course_session (
training_course_id INTEGER PRIMARY KEY
);
CREATE TABLE acq_training_enrolment (
training_course_id INTEGER NOT NULL,
acq_staff_acq_person_id INTEGER NOT NULL
);
-- insert
INSERT INTO acq_staff VALUES (1), (2), (3);
INSERT INTO acq_training_course_session VALUES (1), (2), (3), (4);
INSERT INTO acq_training_enrolment VALUES (1,1), (1,2), (2,1), (3,1);
-- fetch
INSERT INTO acq_training_enrolment (training_course_id, acq_staff_acq_person_id)
SELECT 3, 1 WHERE NOT EXISTS
(SELECT *
FROM acq_training_course_session
INNER JOIN acq_training_enrolment
ON acq_training_course_session.training_course_id = acq_training_enrolment.training_course_id
INNER JOIN acq_staff ON acq_training_enrolment.acq_staff_acq_person_id = acq_staff.acq_person_id
WHERE acq_training_course_session.training_course_id = 3
AND acq_staff.acq_person_id = 1)
;
Try it here: https://onecompiler.com/mysql/3yk7xynkg

I guess you can do something like this: How can I simulate a print statement in MySQL?
`mysql>SELECT 'some text' as '';
+-----------+
| |
+-----------+
| some text |
+-----------+
1 row in set (0.00 sec)`
and just instead of some text set -1.
And one more thing i noticed in your question, that part "if those 3 conditions are satisfied" if you want all 3 conditions to be satisfied you need to change OR to AND. Because in your case, with OR, there needs to be satisfied only 1 condition, but with AND all 3 of them need to be satisfied.

maybe you can try that
select
if(
acq_staff.acq_person_id = staffID , '-1' ,
if(
acq_training_course_session.training_course_id = course_id , '-1' ,
if(acq_training_enrolment.acq_staff_acq_person_id = staffID , '-1' , 'not exist')
)
) as "check" from acq_staff , acq_training_course_session , acq_training_enrolment limit 1

The question is about how to conditionally execute an insert query. In pseudo-code, the question asks how to do the following
flag = (SELECT ... WHERE <all the conditions are met>)
IF flag == 1
INSERT INTO ....
ELSE IF flag == -1
DO NOTHING
Now think about it this way
result_set = (SELECT ... WHERE <all the conditions are met>)
# result_set here is the actual rows we want to insert
# length(result_set) > 0 if conditions are met
# length(result_set) == 0 if conditions are not met
INSERT INTO ... (result_set)
or simply
INSERT INTO ... (SELECT ... WHERE <all the conditions are met>)
When <all the conditions are met>, the insert will actually have something to insert. Otherwise, it will have an empty result set so no rows will be inserted.
So use INSERT INTO ... SELECT ... WHERE <all the conditions are met> Syntax to achieve desired results. Unfortunately, this solution does not have a way to return back -1.

Related

MySQL - copy or update rows with a change within one table

I have a database table like this one:
group | detailsID | price
EK | 1 | 1.40
EK | 2 | 1.50
EK | 3 | 1.60
H | 1 | 2.40
H | 2 | 2.50
Now I want to copy the data from group "EK" to the group "H", so the prices for the detailsID's must be adjusted for the detailsIDs 1 and 2, and the entry for detailsID 3 must be inserted for group "H".
How can I do that with one or two MySQL query's?
Thanks!
We can try doing an INSERT INTO ... SELECT with ON DUPLICATE KEY UPDATE:
INSERT INTO yourTable (`group`, detailsID, price)
SELECT 'H', detailsID, price
FROM yourTable t
WHERE `group` = 'EK'
ON DUPLICATE KEY UPDATE price = t.price;
But this assumes that there exists a unique key on (group, detailsID). If this would not be possible, then this approach would not work.
As an alternative, I might do this in two steps. First, remove the H group records, then insert the updated H records you expect.
DELETE
FROM yourTable
WHERE `group` = 'H';
INSERT INTO yourTable (`group`, detailsID, price)
SELECT 'H', detailsID, price
FROM yourTable
WHERE `group` = 'EK';
I use the above approach because a single update can't handle your requirement, since new records also need to be inserted.
Note that you should avoid naming your columns and tables using reserved MySQL keywords such as GROUP.
You can try this as well, Following code implemented using stored procedures. Very simple not that difficult to understand. You may need to modify data type and optimize the code as per the requirement.
DELIMITER $$;
DROP PROCEDURE IF EXISTS update_H $$;
CREATE PROCEDURE update_H()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE `group_col` varchar(255) DEFAULT "";
DECLARE `detaildid_col` varchar(255) DEFAULT "";
DECLARE `price_col` varchar(255) DEFAULT "";
DECLARE H_FOUND INTEGER DEFAULT 0;
DECLARE pull_data CURSOR FOR select `group`, `detaildid`, `price` from test.newtab WHERE `group` = 'EK';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN pull_data;
traverse_data: LOOP
FETCH pull_data INTO group_col, detaildid_col, price_col;
IF finished = 1 THEN
LEAVE traverse_data;
END IF;
SET H_FOUND = (SELECT count(*) from test.newtab where `group` = 'H' AND `detaildid` = detaildid_col);
IF ( H_FOUND = 1 ) THEN
UPDATE test.newtab SET `price` = price_col where `group` = 'H' AND `detaildid` = detaildid_col;
ELSE
INSERT INTO test.newtab (`group`, `detaildid`, `price`) VALUES ('H', detaildid_col, price_col);
END IF;
END LOOP traverse_data;
CLOSE pull_data;
END $$;
DELIMITER ;
You can call this procedure by executing, call update_H();

Insert string into mysql multiple times, removing last character each time, with one query

Using MySQL, I'm looking to write a single insert query that will take a single string and insert it multiple times, each time removing the last character.
So the query would be something like
INSERT INTO table (str) VALUES ("string") .....
and would result in the following values being inserted
string
strin
stri
str
st
s
I could do this PHP, but I'm wondering if there is an SQL solution first.
This approach requires that you create another table and prepopulate it with numbers, but it's easy to do and makes sense if this is something you will have to do repeatedly. I just tested this in SQLFiddle
create table table1 (string1 varchar(10));
create table table2 (number1 integer);
insert into table2 values (1);
insert into table2 values (2);
insert into table2 values (3);
insert into table2 values (4);
insert into table2 values (5);
insert into table2 values (6);
insert into table2 values (7);
insert into table2 values (8);
insert into table2 values (9);
insert into table2 values (10);
insert into table1 (string1)
select left(stringval, number1)
from (select 'ninechars' as stringval ) as a
join table2 on table2.number1 <= char_length(a.stringval)
select * from table1
STRING1
n
ni
nin
nine
ninec
ninech
ninecha
ninechar
ninechars
Of course, table2 in this case must have enough rows for the max length of the string you need to insert.
If you have a table of numbers, you could do:
insert into table(str)
select left(#str, n.n)
from (select 1 as n union all select 2 union all select 3 union all select 4 union all
select 5 union all select 6 union all select 7 union all select 8 union all select 9
) n
where length(#str) >= n.n
order by n.n desc;
The simplest way is to write a stored procedure and then just call it to do the inserts.
DELIMITER #
CREATE PROCEDURE 'insert_string_rows' (IN 'str' text)
BEGIN
DECLARE len int unsigned;
SET len = CHAR_LENGTH(str);
WHILE len > 0 DO
INSERT INTO table VALUES (str);
SET str = SUBSTR(str, 1, len - 1);
SET len = CHAR_LENGTH(str);
END WHILE;
END#
DELIMITER ;
Then just simply
CALL insert_string_rows ("string")
and out pops all the rows into 'table'
string
strin
stri
str
st
s

trigger for a compostite key and update another column

I have two tables: threads and threadreply.
threads has a composite primary key, (thread_id,reply_id).
When I insert a new row into threadreply, I need to:
update my column threads.reply_count by adding +1 to the previous value; and
insert data into threadreply by adding +1 to the MAX(reply_id) with same thread_id.
Using the following trigger, I was able to add+1 to my reply_id, but couldn't get to update my reply_count:
CREATE TRIGGER addone BEFORE INSERT ON threadreply
FOR EACH ROW BEGIN
SET NEW.reply_id = (
SELECT IFNULL(
(
SELECT MAX(reply_id) + 1
FROM threadreply
WHERE thread_id = NEW.thread_id
),
1
)
);
END
How can I solve this?
I assume that there is a typo in the question and the composite key (thread_id,reply_id) exists in the threadreply table, not in the threads table.
The trigger might look like:
CREATE TRIGGER addone BEFORE INSERT ON threadreply
FOR EACH ROW BEGIN
SET NEW.reply_id = (
SELECT IFNULL(
(
SELECT MAX(reply_id) + 1
FROM threadreply
WHERE thread_id = NEW.thread_id
), 1
)
);
UPDATE threads SET reply_count = reply_count + 1
WHERE thread_id = NEW.thread_id;
END
/
Take a look at this demo: --> http://www.sqlfiddle.com/#!2/1e7bb/2
The trigger and insert statements are on the left side in the schema window, below are shown results of the demo.

Update data based on previous row combination values

I have a MySQL table with the following structure:
ID
CatLevel1 CatLevel2 CatLevel3 ... CatLevel6 AcctLevel1 AcctLevel2 ... AcctLevel6
(6 columns for CatLevel, from 1 to 6) and 6 columns for AcctLevel, from 1 to 6).
Beginning with AcctlLevel1, I need to update it depending on the values found in the Catelevel fields in the following manner:
Begin iteration on CatLevel1. Initial value for AcctLevel1 -> 01.
If CatLevel1 Row(n) <> CatLevel1 Row(n-1) then AcctLevel1 -> 02.
meaning that each time a new value (not matching the previous row) is found in CatLevel1, increase the AcctLevel1 by 1 also adding a leading zero for values less than 10.
When the last row in CatLevel1 has been iterated, then begin with CatLevel2 and iterate through it in the same manner.
I was wondering which way to go, to break it down in smaller pieces and code it with PHP or to do it all in MySQL with some sort or recursiveness?
Many of you will think I'm asking for the solution, but I'm really asking for some ideas to get me started because I'm a bit confused on how to go.
Based on your requirement I've come with with the following.
The first Update does a necessary reset.
The second causes AcctLevel1 to be 1 whenever there is a change with the previous row.
The third Update sums up these 1 to create the final result.
Data:
create table data
(
id int,
CatLevel1 varchar(5),
AcctLevel1 varchar(5)
);
insert into data values (0,'1','0');
insert into data values (1,'2','0');
insert into data values (2,'1','1');
insert into data values (3,'2','1');
insert into data values (4,'2','1');
SQL Commands:
UPDATE `data` t1 SET AcctLevel1 = 0;
update `data` t1
left outer JOIN `data` t2
on t1.id-1 = t2.id
set t1.AcctLevel1 =
case when t1.CatLevel1 = t2.CatLevel1 then t1.AcctLevel1
else t2.AcctLevel1+1 end;
update `data` t1
set t1.AcctLevel1 =
( select SUM(TEMP.AcctLevel1) from (SELECT *FROM `data`) AS TEMP where TEMP.ID <= t1.ID );
SQL Fiddle: http://sqlfiddle.com/#!2/8fb647/2
2ND SQL Fiddle:http://sqlfiddle.com/#!2/c047bc/1
Update: Final Toy Query
UPDATE `data` t4
SET AcctLevel1 =
(
SELECT CASE WHEN TEMP.SCHANGES IS NULL THEN 0 ELSE TEMP.SCHANGES END from
(SELECT T3.ID,
(SELECT SUM(CASE WHEN t1.CatLevel1 = t2.CatLevel1 THEN 0 ELSE 1 END) AS SUM_CHANGES
FROM `data` t1,
`data` t2
WHERE t1.id-1 = t2.id
AND t1.ID <= t3.ID) AS SCHANGES
FROM `DATA` t3 ) as TEMP where TEMP.ID = T4.ID
);
Final JSFiddle: http://sqlfiddle.com/#!2/325f16/2

Addition in MySQL trigger not working as expected

I'm doing some addition as part of a mysql trigger. The added value is added a to a column on the table. The code is as follows;
BEGIN
IF NEW.Status = 'processed' AND NEW.Success = 1 THEN
INSERT INTO crm_master
(msisdn, last_action_date, source, contract_type, revenue,inc)
VALUES
(new.msisdn,NOW(), 'INC5', new.Contract_Type, revenue = revenue+5, 1)
ON DUPLICATE KEY UPDATE last_action_date = NOW(),
contract_type = new.Contract_Type,
revenue = revenue+5,
inc = 1;
END IF;
END
The column revenue in the table crm_master is set to default of 0
The problem is that I'm getting unexpected results with incorrect values and in some cases 0 even though there should never be a 0 value.
I don't think it's valid reference to default value revenue = revenue+5 in your insert statement. It should look like
INSERT INTO crm_master
(msisdn, last_action_date, source, contract_type, revenue,inc)
VALUES
(new.msisdn,NOW(), 'INC5', new.Contract_Type, DEFAULT(revenue) +5, 1)
ON DUPLICATE KEY UPDATE ....
Or you can simply do
INSERT INTO ....
VALUES
(new.msisdn,NOW(), 'INC5', new.Contract_Type, 5, 1) ...
*Your update part of INSERT ... ON DUPLICATE KEY UPDATE is ok.
INSERT INTO sometable( column ) VALUES ( column = column + 5 );
is equivalent to
INSERT INTO sometable( column ) VALUES ( 0 );
because (column = column+5) evaluates to 0 as column is never equal to column+5.
This syntax is ok for UPDATE query, but for INSERT you should provide an explicit value, like
INSERT INTO sometable( id, column ) VALUES ( 1, 5 )
ON DUPLICATE KEY UPDATE column = column + 5;
which would insert value 5 if there is no row with given id and add 5 to column if there is one.