MySQL stored procedure has just stopped working - mysql

I have the following stored procedure setup and it has just stopped working in the last few days. Does anyone know why this could just stop working? None of the database tables have changed.
drop procedure if exists bookings_by_voucher;
delimiter //
create procedure bookings_by_voucher(in start_date date, in end_date date, l_id int)
language sql
deterministic
sql security definer
begin
declare s text;
select distinct group_concat(concat('sum(if(c.gross_value = ',gross_value,',c.net_value,0)) coupon',
cast(gross_value as unsigned))) from coupons into s;
set #query = concat('select ',if(l_id is null, '"All Locations"','l.location_name'),
' location_name,ifnull(b.places, 0) as places, ',
if(start_date is null and end_date is null,'"All Dates"',
if(start_date is null, concat('" <= ',end_date,'"'),
if(end_date is null,concat('" >= ',start_date,'"'),
concat('"',start_date,' - ',end_date,'"')
)
)
),' dates,',
ifnull(s,'"No Coupons"'),
',round(sum(b.price/1.2-ifnull(c.net_value,0)), 2) paidbycard from locations l join bookings b ',
' on l.id = b.location_id ',
concat(if(start_date is null,'',concat(' and b.date >= "', start_date,'"'))),
concat(if(end_date is null,'',concat(' and b.date <= "', end_date,'"'))),
' left join coupons c on b.voucher_code = c.code',
if (l_id is null, ' group by l.id', concat(' where l.id = ', l_id) ));
/*select #query;*/
prepare stmt from #query;
execute stmt;
end//
The error that I am getting back from my application (built in Laravel 5.1) is:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an
error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'paidbycard
from locations l join bookings b on l.id = b.location_id left join
' at line 1 (SQL: call bookings_by_voucher(null, null, null))

I have found something, If I am not wrong, after your "group by" clause there is "where" clause.

Related

SQL Query to Join Multiple Tables in Sandbox

I'm writing a query to combine data from multiple tables within a sandbox environment. I'm getting a SQL 1100 error message on first CREATE TABLE after the DROP.
Error message:
SQL Error [1100] [HY000]: ERROR: 'CREATE TABLE
Sandbox..CF_Promocodeused AS ( SELECT DISTINCT visitid, visitdate,
post_evar23, post_evar16, post_evar17, post_evar10 FROM
IDM..HITDATAHISTORY WHERE brandcode = ‘FDM’ AND post_evar23 IS NOT
NULL )' error
^ found "‘" (at char 179) Illegal initial character in identifier
I welcome any ideas from the community. Thank you in advance.
Code used:
DROP TABLE Sandbox..CF_Promocodeused IF EXISTS;
CREATE TABLE Sandbox..CF_Promocodeused AS
(
SELECT DISTINCT visitid, visitdate, post_evar23, post_evar16, post_evar17, post_evar10
FROM IDM..HITDATAHISTORY
WHERE brandcode = ‘FDM’
AND post_evar23 IS NOT NULL
)
;
DROP TABLE Sandbox..CF_Promocodeused1 IF EXISTS;
CREATE TABLE Sandbox..CF_Promocodeused1 AS (
SELECT DISTINCT post_evar23, visitdate, post_evar16, post_evar17, post_evar10, COUNT(DISTINCT visitid) AS visits, calendardate, subtotalamount
FROM IDM..Sandbox..CF_Promocodeused AS h
INNER JOIN IDM..ORDERFACT AS o ON h.ordernumber = o.ordernumber
INNER JOIN IDM..DATEDIM AS d ON d.fiscalmonthname = h.fiscalmonthname
WHERE calendardate BETWEEN '01/27/2021 00:00:00’ AND 02/23/2021 23:59:59'
AND subtotalamount >= '200.00'

I want when no filters are selected then return all the data with the count

I'm creating a store which would run according to selected filter for example when studentid is passed then it will return all the data with count of records. When schoolid is passess then it will return all the data wrt to schoolid and count of records. Similarly i want when none of the filter is selected then return all the data with count of records. Currently it is showing error "#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ELSE
SELECT SQL_CALC_FOUND_ROWS DISTINCT
map.idnstudent as Student_Count,ma' at line 21".
Please help me on this i need help big time. I've tried all possible solution till now.
DROP PROCEDURE IF EXISTS `TestspPendingTab_filter_all123`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `TestspPendingTab_filter_all123`(IN `no_filter_data` VARCHAR(500), IN `search_keyword` VARCHAR(50), IN `Stud_id_filter` VARCHAR(100), IN `sch_id_filter` VARCHAR(100), IN `Subj_id_filter` VARCHAR(100), IN `start_date_filter` DATE, IN `end_date_filter` DATE, OUT `recordfound` INT(10))
BEGIN
CASE WHEN no_filter_data = 'YES' THEN
SELECT SQL_CALC_FOUND_ROWS DISTINCT
map.idnstudent as Student_Count,map.idnstudent as student_id,usr.name as student_name,
map.idnsubject as Subject_Count,map.idnsubject as subject_id,sn.sub_name as subject_name,
s.id as School_Count,s.id as school_id,ifnull(s.schoolname,'N/A') AS schoolname
from `user` `usr`
join `student_class_hour_map` `map` on `map`.`idnstudent`=`usr`.`id` and `usr`.`flag_status`=1
left join `subject_name` `sn` on `sn`.`id` = `map`.`idnsubject`
left join `school_student_rel` `ssrl` on `ssrl`.`student_id`=`map`.`idnstudent`
left join `school` `s` on `s`.`id` = `ssrl`.`school_id`
WHERE 1
AND map.archivestatus=0
AND recordfound = FOUND_ROWS()
ELSE
SELECT SQL_CALC_FOUND_ROWS DISTINCT
map.idnstudent as Student_Count,map.idnstudent as student_id,usr.name as student_name,
map.idnsubject as Subject_Count,map.idnsubject as subject_id,sn.sub_name as subject_name,
s.id as School_Count,s.id as school_id,ifnull(s.schoolname,'N/A') AS schoolname
from `user` `usr`
join `student_class_hour_map` `map` on `map`.`idnstudent`=`usr`.`id` and `usr`.`flag_status`=1
left join `subject_name` `sn` on `sn`.`id` = `map`.`idnsubject`
left join `school_student_rel` `ssrl` on `ssrl`.`student_id`=`map`.`idnstudent`
left join `school` `s` on `s`.`id` = `ssrl`.`school_id`
WHERE 1
AND map.archivestatus=0
AND
CASE WHEN search_keyword != '' THEN
(s.schoolname like CONCAT('%', search_keyword, '%') OR sn.sub_name like CONCAT('%', search_keyword, '%') OR usr.name like CONCAT('%', search_keyword, '%'))
ELSE
1
END
AND
CASE WHEN Stud_id_filter != '' THEN
FIND_IN_SET(map.idnstudent,Stud_id_filter)
ELSE 1
END
AND
CASE
WHEN sch_id_filter != '' THEN
FIND_IN_SET(s.id,sch_id_filter)
ELSE
1
END
AND
CASE
WHEN Subj_id_filter != '' THEN
FIND_IN_SET(map.idnsubject,Subj_id_filter)
ELSE
1
END
AND
CASE
WHEN start_date_filter != '' AND end_date_filter != '' THEN
map.startdate >= start_date_filter and map.enddate <= end_date_filter
ELSE
1
END
END
GROUP BY
CASE WHEN stud_id_filter <> '' THEN map.idnstudent END,
CASE WHEN sch_id_filter <> '' THEN s.id END,
CASE WHEN subj_id_filter <> '' THEN map.idnsubject END;
SET recordfound = FOUND_ROWS();
END$$
DELIMITER ;
Expected output : It should return all the data with count of records when none of the filter is selected. If any filter is selected then return data according to that filter with count of records.
In stored-procedure code of the form
CASE
WHEN something
THEN query1;
ELSE query2;
you need semicolons after the queries. You don't have them.
Your code is a little confusing because you're using CASE both for control flow and as SELECT logic. It's the control flow that needs semicolons/

Mysql query to print attendance sheet

Please some one help me tI have two Tables in my MYSQL database,
the first table - (Employee Table) consists of
EmployeeNo| EmployeeName
the second table - (Attendance table) consists of
DATE | TIME | STATUS| EmployeeNo
and a calendar table that holds only date for every month
I want to generate attendance sheet similar to this
Click here
I end up writing the following SQL, but it gives me syntax error
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'from (select cal.calendarDate,
emp.first_name,emp.nu' at line 2
and my query ,
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(CASE WHEN calemp.calendarDate = ''',date_format(calendarDate, '%Y-%m-%d'),''' THEN coalesce(att.inorout, ''P'') END) AS `',date_format(calendarDate, '%Y-%m-%d'), '`'
)
) INTO #sql
FROM yearly_date_calendar
where calendarDate >= '2016-11-01'
and calendarDate <= '2016-11-30';
SET #sql = CONCAT('SELECT calemp.first_name,calemp.nurse_code,',#sql,'
from
(
select cal.calendarDate,emp.first_name,emp.nurse_code
from yearly_date_calendar cal
cross join syscare_caregiver emp
) calemp
left join syscare_employee_attendance att
on calemp.nurse_code = att.emp_code
and calemp.calendarDate = att.attendance_date
where calemp.calendarDate>=''2016-11-01''
and calemp.calendarDate <= ''2016-11-30''
group by calemp.first_name, calemp.nurse_code,calemp.calendarDate
');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
You can use below query and fetch all database result
select EmployeeTable.EmployeeNo,Employee Table.EmployeeName,Attendance table.DATE,Attendance table.TIME,Attendance table.STAUS,Attendance table.EmployeeNo from Employee Table INNER JOIN Attendance table ON
EmployeeTable.EmployeeNo=Attendance table.EmployeeNo

MySQL prepared statement in a stored procedure not behaving as expected

I have this MySQL Stored Procedure
DELIMITER $$
CREATE DEFINER=`dbuser`#`%` PROCEDURE `getTranslatedAnswer`(IN questionDesc VARCHAR(2500), col VARCHAR(10))
BEGIN
SET #paramVal = questionDesc;
SET #str = CONCAT('SELECT C.',col,' AS `answer`, D.',col,' AS `message`
FROM `option_group` A
INNER JOIN `questions_answers` B ON A.`option_id` = B.`option_id`
INNER JOIN `answers` C ON B.`answers_id` = C.`answers_id`
INNER JOIN `chat_message` D ON A.`option_group_id` = D.`option_group_id`
WHERE UPPER(`A`.',col,') = ? LIMIT 1');
PREPARE stmt FROM #str;
EXECUTE stmt USING #paramVal;
DEALLOCATE PREPARE stmt;
END
The above code when called using
call getTranslatedAnswer('我可以在机场买到预付SIM卡吗?','zh_chs');
will return 0 rows. Compared to as when I call the bare SQL below
SELECT C.zh_chs AS `answer`, D.zh_chs AS `message`
FROM `option_group` A
INNER JOIN `questions_answers` B ON A.`option_id` = B.`option_id`
INNER JOIN `answers` C ON B.`answers_id` = C.`answers_id`
INNER JOIN `chat_message` D ON A.`option_group_id` = D.`option_group_id`
WHERE UPPER(`A`.`zh_chs`) = '我可以在机场买到预付SIM卡吗?' LIMIT 1;
it returns 1 row. Am I missing something here? How do I debug this? Please advise, thanks!
I could be remembering wrong, but I seem to recall execute not actually returning results as you expecting it to.
What happens if you try something like this?
DELIMITER $$
CREATE DEFINER=`dbuser`#`%` PROCEDURE `getTranslatedAnswer`(IN questionDesc VARCHAR(2500), col VARCHAR(10))
BEGIN
SET #paramVal = questionDesc;
DROP TEMPORARY TABLE IF EXISTS `t_getTranslatedAnswer`;
SET #str = CONCAT('
CREATE TEMPORARY TABLE `t_getTranslatedAnswer`
SELECT C.',col,' AS `answer`, D.',col,' AS `message`
FROM `option_group` A
INNER JOIN `questions_answers` B ON A.`option_id` = B.`option_id`
INNER JOIN `answers` C ON B.`answers_id` = C.`answers_id`
INNER JOIN `chat_message` D ON A.`option_group_id` = D.`option_group_id`
WHERE UPPER(`A`.',col,') = ? LIMIT 1');
PREPARE stmt FROM #str;
EXECUTE stmt USING #paramVal;
DEALLOCATE PREPARE stmt;
SELECT * FROM `t_getTranslatedAnswer`;
DROP TEMPORARY TABLE `t_getTranslatedAnswer`;
END

FIND_IN_SET slow, can't use IN()

I have a stored procedure and it's running slow. Is there a better way to pass the table id's to the procedure rather that use FIND_IN_SET?
The table column e.fk_trans_history_id is an INT(32)
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `1_trans_hist_ent_items_sel`(b INT,tid TEXT)
BEGIN
SELECT
e.id,
e.fk_trans_history_id,
e.fk_prod_pack_id,
e.line_num,
e.vat_code,
e.code,
e.make,
e.model,
e.price,
e.discount,
e.cover,
e.warranty,
p.make,
p.model,
p.weight,
p.width,
p.depth,
p.height,
p.cost,
p.cover_value_each,
p.web_model,
k.stock - k.repair
FROM
1_trans_history_entries e
LEFT JOIN
1_products p ON p.id = e.fk_prod_pack_id
AND LEFT(code, 1) <> 'P'
LEFT JOIN
1_stock k ON k.fk_products_id = p.id AND k.branch = b
WHERE
(e.code IN ('MiscShip' , 'Collect')
OR (ASCII(e.code) > 47
AND ASCII(e.code) < 58))
AND FIND_IN_SET(e.fk_trans_history_id, tid)
ORDER BY e.id;
END
Put the IDs you want to match into a temporary table, and join with that table.
CREATE TEMPORARY TABLE temp_trans_hist_ent_items_sel_ids (
id
);
INSERT INTO temp_trans_hist_ent_items_sel_ids VALUES (1), (10), ...;
Then the query in the procedure can use:
JOIN temp_trans_hist_ent_items_sel_ids AS temp ON e.fk_trans_history_id = temp.id
I found the best and the fastest is to prepare a query like this.
CREATE DEFINER=`root`#`localhost` PROCEDURE `1_trans_hist_ent_items_sel`(b INT, tid TEXT)
BEGIN
--
SET #query=CONCAT( '
SELECT
e.id,
e.fk_trans_history_id,
e.fk_prod_pack_id,
e.line_num,
e.vat_code,
e.code,
e.make,
e.model,
e.price,
e.discount,
e.cover,
e.warranty,
p.make,
p.model,
p.weight,
p.width,
p.depth,
p.height,
p.cost,
p.cover_value_each,
p.web_model,
k.stock - k.repair
FROM
1_trans_history_entries e
LEFT JOIN
1_products p ON p.id = e.fk_prod_pack_id
AND LEFT(code, 1) <> \'P\'
LEFT JOIN
1_stock k ON k.fk_products_id = p.id AND k.branch = ',b,'
WHERE
(e.code IN (\'MiscShip\' , \'Collect\')
OR (ASCII(e.code) > 47
AND ASCII(e.code) < 58))
AND e.fk_trans_history_id IN(' , tid , ')
ORDER BY e.id;');
--
PREPARE sql_query FROM #query;
EXECUTE sql_query;
--
SET #query = '';
--
END
Thanks to Stephen Bouffe. My code is shorter and it would be easier to understand and implement this solution. In my case, it looks like this
SET #query=CONCAT( '
DELETE FROM markup
WHERE id IN (', #ids, ');
');
PREPARE sql_query FROM #query;
EXECUTE sql_query;
Where #ids is a string like '7,12,52'.
It works significantly faster then FIND_IN_SET.