I have the query below and it works exactly as I want EXCEPT I need to be able to include a where clause with the declared variable of startDate and endDate. I keep getting an error on the variables.
DROP PROCEDURE IF EXISTS `reportNameTest`//
-- Creates new procedure
CREATE PROCEDURE reportNameTest (
IN logId varchar (50),
IN fromDate varchar (50),
IN toDate varchar (50)
)
BEGIN
DECLARE logInS varchar (50);
DECLARE startDate varchar (50);
DECLARE endDate varchar (50);
SET startDate = FROM_UNIXTIME(fromDate/1000);
SET endDate = FROM_UNIXTIME(toDate/1000);
SET #tbl = CONCAT('log',logId);
SET #s = CONCAT(
'SELECT g.groupId,g.name AS groupName,l.logId,l.name AS logName,
lr.userId,completed,
g1.parentId AS parentId1, g1.name AS group1Name,g2.parentId AS parentId2, g2.name AS group2Name,
g3.parentId AS parentId3, g3.name AS group3Name,u.name,u.userId,lr.*
FROM logs l
INNER JOIN activities a ON l.logid = a.logid
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN ' ,#tbl);
SET #V = CONCAT (#s,' lr ON lr.activityID = a.activityID
INNER JOIN users u ON u.userID = lr.userID' );
SET #W = CONCAT (#V,'WHERE l.completed
BETWEEN startDate
AND endDate');
PREPARE stmt FROM #V;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
I am open to any suggestions!
Thank you
First of all, as #neutrino points out, you're missing a space between lr.userID and WHERE. To see this you could return the query with select #W instead of the prepare and execute. Then try to run that query in a normal mysql commander.
Or you can check the query/general log for the query that fails and find the missing space.
Second, you don't need to build you query in several steps like that, it's probably easier to read if you just do one long change of concat.
There are several problems with your code:
You are producing unnecessary variables when building a query string. #S -> #V -> #W. But then you prepare your statement from #V which doesn't contain the complete query string.
Instead of concatenating values of variables startDate and endDate you put their names in a string literal.
Values of startDate and endDate should be quoted.
You don't use logInS variable even though you declared it.
In your case you need only one variable (unless you do something meaningful with them like validating for example) that will hold a query string.
That being said try it this way
DELIMITER //
CREATE PROCEDURE reportNameTest(
IN logId VARCHAR(50),
IN fromDate VARCHAR(50),
IN toDate VARCHAR(50))
BEGIN
SET #sql = CONCAT(
'SELECT g.groupId, g.name AS groupName, l.logId,l.name AS logName,
lr.userId,completed,
g1.parentId AS parentId1, g1.name AS group1Name,g2.parentId AS parentId2, g2.name AS group2Name,
g3.parentId AS parentId3, g3.name AS group3Name,u.name,u.userId,lr.*
FROM logs l
INNER JOIN activities a ON l.logid = a.logid
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN log', logId, ' lr ON lr.activityID = a.activityID
INNER JOIN users u ON u.userID = lr.userID
WHERE l.completed BETWEEN \'', FROM_UNIXTIME(fromDate / 1000),
'\' AND \'', FROM_UNIXTIME(toDate / 1000), '\'');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
That should work just fine assuming that you resulting query itself is correct.
Here is SQLFiddle demo that outputs the resulting query string instead of executing it.
Related
I am building up a website and I am working on the search part of it at the moment, so what I am trying to do is create a stored procedure that I am able to call that returns the values that I need.
I have put this together so far, but this limits me to only being able to select for example one model_id. I want to be able to search for model_ids 1,2,3,4 (example).
I was thinking of adding the parameters in as a string like '1,2,3,4' then splitting them and adding it into a temp table then I could do something like -product_type_id IN (select * from p_product_type_id)
PROCEDURE `sp_advert_search_load`(
IN p_product_type_id varchar(255),
IN p_product_details_id INT,
IN p_advert_status_id INT,
IN p_advert_type_id INT,
IN p_manufacturer_id INT,
IN p_model_id INT,
IN p_mechanism_id INT,
IN p_calibre_id INT,
IN p_orientation_id INT,
IN p_chamber_type_id INT,
IN p_trigger_type_id INT,
IN p_condition_id INT,
IN p_barrel_type_id INT,
IN p_cased INT,
IN p_certificate_id INT ,
IN p_price_more_than FLOAT ,
IN p_price_less_than FLOAT)
BEGIN
SELECT * FROM all_information_without_images
WHERE (product_type_id IN (p_product_type_id) or p_product_type_id IS NULL)
and (product_details_id = p_product_details_id or p_product_details_id IS NULL)
and (advert_status_id = p_advert_status_id or p_advert_status_id IS NULL)
and (advert_type_id = p_advert_type_id or p_advert_type_id IS NULL)
and (manufacturer_id = p_manufacturer_id or p_manufacturer_id IS NULL)
and (model_id = p_model_id or p_model_id IS NULL)
and (mechanism_id = p_mechanism_id or p_mechanism_id IS NULL)
and (calibre_id = p_calibre_id or p_calibre_id IS NULL)
and (orientation_id = p_orientation_id or p_orientation_id IS NULL)
and (chamber_type_id = p_chamber_type_id or p_chamber_type_id IS NULL)
and (trigger_type_id = p_trigger_type_id or p_trigger_type_id IS NULL)
and (condition_id = p_condition_id or p_condition_id IS NULL)
and (barrel_type_id = p_barrel_type_id or p_barrel_type_id IS NULL)
and (cased = p_cased or p_cased IS NULL)
and (certificate_id = p_certificate_id or p_certificate_id IS NULL)
and (price >= p_price_more_than or p_price_more_than IS NULL)
and (price <= p_price_less_than or p_price_less_than IS NULL);
END
Is there a better way I could achieve this? I suspect creating the temp tables is going to slow everything down quite a lot. Any pointers would be very helpful.
Thanks,
Richard
I have tried to use a prepared statement:
PROCEDURE `sp_advert_search_load`(
IN p_product_type_id varchar(255),
BEGIN
set #sql = concat( 'SELECT * FROM all_information_without_images
WHERE (product_type_id IN (',p_product_type_id,'))
');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
But I am getting an error 1615 - Prepared statement needs to be re-prepared is might be worth noting that all_information_without_images is a view.
I was thinking about just adding my view code to the prepared statement but it is very long and I think it exceeds the max length.
I am running out of ideas here.
Hello for anyone that wants to know how I managed to do this here is the code below:
First I used a function to split strings like '1,2,3,4' and insert then into a temp table:
BEGIN
# Temp table variables
SET #tableName = 'tmpSplit';
SET #fieldName = 'variable';
# Dropping table
SET #sql := CONCAT('DROP TABLE IF EXISTS ', #tableName);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Creating table
SET #sql := CONCAT('CREATE TEMPORARY TABLE ', #tableName, ' (', #fieldName, ' VARCHAR(1000))');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Preparing toSplit
SET #vars := toSplit;
SET #vars := CONCAT("('", REPLACE(#vars, ",", "'),('"), "')");
# Inserting values
SET #sql := CONCAT('INSERT INTO ', #tableName, ' VALUES ', #vars);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Returning record set, or inserting into optional target
IF target IS NULL THEN
SET #sql := CONCAT('SELECT TRIM(`', #fieldName, '`) AS `', #fieldName, '` FROM ', #tableName);
ELSE
SET #sql := CONCAT('INSERT INTO ', target, ' SELECT TRIM(`', #fieldName, '`) FROM ', #tableName);
END IF;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
Then the main store prod created a temp table then used the function to insert a varchar value into a temp table then
WHERE
CASE WHEN #product_type_id = ''
THEN information_view.product_type_id = information_view.product_type_id
ELSE information_view.product_type_id IN (select * from tm_product_type_id)end;
PROCEDURE `sp_advert_search_load`(
IN p_product_type_id varchar(255)
)
BEGIN
DROP TEMPORARY TABLE IF EXISTS tm_product_type_id;
CREATE TEMPORARY TABLE tm_product_type_id (product_type_id int);
SET #product_type_id = ifnull(p_product_type_id,'');
CALL sp_split(#product_type_id,'tm_product_type_id');
SELECT * FROM ( SELECT
e.entity_id AS entity_id,
e.entity_type_id AS entity_type_id,
enty.entity_description AS entity_description,
e.title_id AS title_id,
t.title AS title,
e.first_name AS first_name,
e.last_name AS last_name,
e.street_line_1 AS street_line_1,
e.street_line_2 AS street_line_2,
e.street_line_3 AS street_line_3,
e.town AS town,
e.county AS county,
e.postcode AS postcode,
e.email AS email,
e.telephone AS telephone,
e.company_name AS company_name,
e.company_desc AS company_desc,
e.website AS website,
e.concent AS concent,
e.longi AS longitude,
e.lati AS latitude,
a.advert_id AS ad_advert_id,
a.title AS ad_title,
a.advert_id AS advert_id,
a.description AS advert_description,
a.advert_status_id AS advert_status_id,
ads.description AS ad_statid,
a.advert_type_id AS advert_type_id,
avt.description AS ad_type,
a.product_details_id AS product_details_id,
a.price AS price,
a.created AS created_date,
pd.product_description AS product_description,
pd.product_type_id AS product_type_id,
pt.description AS product_type_description,
g.gun_id AS gun_id,
g.manufacturer_id AS manufacturer_id,
mg.manufacturer AS manufacturer,
g.model_id AS model_id,
mo.model AS model,
g.mechanism_id AS mechanism_id,
mec.mechanism AS mechanism,
g.calibre_id AS calibre_id,
cal.calibre AS calibre,
g.orientation_id AS orientation_id,
org.orientation AS orientation,
g.chamber_type_id AS chamber_type_id,
cht.chamber_type AS chamber_description,
g.trigger_type_id AS trigger_type_id,
trgt.trigger_type AS trigger_description,
g.condition_id AS condition_id,
con.`condition` AS `condition`,
g.barrel_type_id AS barrel_type_id,
bart.barrel_type AS barrel_description,
g.cased_id AS cased_id,
c.cased AS cased,
g.barrel_length_inches_id AS barrel_length_inches_id,
bli.barrel_length_inches AS barrel_length_inches,
g.barrel_length_inches_fraction_id AS barrel_length_inches_fraction_id,
blif.barrel_length_inches_fraction AS barrel_length_inches_fraction,
g.stock_length_inches_id AS stock_length_inches_id,
sli.stock_length_inches AS stock_length_inches,
g.stock_length_inches_fraction_id AS stock_length_inches_fraction_id,
slif.stock_length_inches_fraction AS stock_length_inches_fraction,
wp.weight_pound_id AS weight_pound_id,
wp.weight_pound AS weight_pound,
wo.weight_ounce_id AS weight_ounce_id,
wo.weight_ounce AS weight_ounce,
g.choke_type_id AS choke_type_id,
chot.choke_type AS choke_type,
g.choke_type_2_id AS choke_type_2_id,
chot2.choke_type AS choke_type_2,
g.ejection_id AS ejection_id,
ejec.ejection AS ejection,
g.certificate_id AS certificate_id,
cert.certificate AS certificate,
g.serial_number AS serial_number,
g.stock_number AS stock_number,
a.url_data AS url_data,
op.optic_id AS optic_id,
op.product_details_id AS optic_product_details_id,
pdop.product_description AS optic_product_description,
op.optic_make_id AS optic_make_id,
om.optic_make AS optic_make,
op.optic_custom_make AS optic_custom_make,
op.optic_model_id AS optic_model_id,
omod.optic_model AS optic_model,
op.optic_custom_model AS optic_custom_model,
op.optic_magnification_id AS optic_magnification_id,
omag.optic_magnification AS optic_magnification,
op.optic_custom_magnification AS optic_custom_magnification,
op.condition_id AS optic_condition_id,
optcon.condition AS optic_condition,
equ.equipment_id AS equipment_id,
equ.equipment_type_id AS equipment_type_id,
equt.equipment_type AS equipment_type,
equ.equipment_make_id AS equipment_make_id,
equm.equipment_make AS equipment_make,
equ.equipment_custom_model AS equipment_custom_model,
equ.condition_id AS equipment_condition_id,
equc.condition AS equipment_condition,
opa.optic_make_id AS optic_advert_optic_make_id,
oma.optic_make AS optic_advert_optic_make,
opa.optic_custom_make AS optic_advert_custom_make,
opa.optic_model_id AS optic_advert_model_id,
omoda.optic_model AS optic_advert_model,
opa.optic_custom_model AS optic_advert_custom_model,
opa.optic_magnification_id AS optic_advert_magnification_id,
omaga.optic_magnification AS optic_advert_magnification,
opa.optic_custom_magnification AS optic_advert_custom_magnification,
opa.condition_id AS optic_advert_condition_id,
optcona.condition AS optic_advert_condition,
img.image_id AS image_id,
img.image_src AS image_src
FROM
tbl_entity e
JOIN tbl_adverts a ON e.entity_id = a.entity_id
LEFT JOIN tbl_entity_type enty ON enty.entity_type_id = e.entity_type_id
LEFT JOIN tbl_title t ON t.title_id = e.title_id
LEFT JOIN tbl_guns g ON a.gun_id = g.gun_id
LEFT JOIN tbl_equipments equ ON a.equipment_id = equ.equipment_id
LEFT JOIN tbl_equipment_type equt ON equt.equipment_type_id = equ.equipment_type_id
LEFT JOIN tbl_equipment_make equm ON equm.equipment_make_id = equ.equipment_make_id
LEFT JOIN tbl_condition equc ON equc.condition_id = equ.condition_id
LEFT JOIN tbl_product_details pd ON a.product_details_id = pd.product_details_id AND a.product_type_id = pd.product_type_id
LEFT JOIN tbl_advert_type avt ON avt.advert_type_id = a.advert_type_id
LEFT JOIN tbl_advert_status ads ON ads.advert_status_id = a.advert_status_id
LEFT JOIN tbl_manufacturer mg ON g.manufacturer_id = mg.manufacturer_id AND mg.product_details_id = a.product_details_id
LEFT JOIN tbl_model mo ON g.product_details_id = mo.product_details_id AND mo.model_id = g.model_id
LEFT JOIN tbl_mechanism mec ON mec.product_details_id = g.product_details_id AND mec.mechanism_id = g.mechanism_id
LEFT JOIN tbl_calibre cal ON cal.product_details_id = g.product_details_id AND cal.calibre_id = g.calibre_id
LEFT JOIN tbl_barrel_type bart ON bart.product_details_id = g.product_details_id AND bart.barrel_type_id = g.barrel_type_id
LEFT JOIN tbl_chamber_type cht ON cht.product_details_id = g.product_details_id AND g.chamber_type_id = cht.chamber_type_id
LEFT JOIN tbl_trigger_type trgt ON trgt.product_details_id = g.product_details_id AND g.trigger_type_id = trgt.trigger_type_id
LEFT JOIN tbl_orientation org ON g.orientation_id = org.orientation_id
LEFT JOIN tbl_condition con ON g.condition_id = con.condition_id
LEFT JOIN tbl_cased c ON g.cased_id = c.cased_id
LEFT JOIN tbl_certificate cert ON cert.product_details_id = g.product_details_id AND cert.certificate_id = g.certificate_id
LEFT JOIN tbl_product_type pt ON a.product_type_id = pt.product_type_id
LEFT JOIN tbl_images img ON a.advert_id = img.advert_id AND img.primary_flag = 'Y'
LEFT JOIN tbl_stock_length_inches sli ON a.product_details_id = sli.product_details_id AND sli.stock_length_inches_id = g.stock_length_inches_id
LEFT JOIN tbl_stock_length_inches_fraction slif ON slif.stock_length_inches_fraction_id = g.stock_length_inches_fraction_id
LEFT JOIN tbl_barrel_length_inches bli ON a.product_details_id = bli.product_details_id AND bli.barrel_length_inches_id = g.barrel_length_inches_id
LEFT JOIN tbl_barrel_length_inches_fraction blif ON blif.barrel_length_inches_fraction_id = g.barrel_length_inches_fraction_id
LEFT JOIN tbl_choke_type chot ON a.product_details_id = chot.product_details_id AND chot.choke_type_id = g.choke_type_id
LEFT JOIN tbl_choke_type chot2 ON a.product_details_id = chot.product_details_id AND chot2.choke_type_id = g.choke_type_2_id
LEFT JOIN tbl_ejection ejec ON g.ejection_id = ejec.ejection_id
LEFT JOIN tbl_weight_pounds wp ON wp.weight_pound_id = g.weight_pound_id
LEFT JOIN tbl_weight_ounces wo ON wo.weight_ounce_id = g.weight_ounce_id
LEFT JOIN tbl_optics op ON op.optic_id = a.optic_id AND a.gun_id IS NOT NULL
LEFT JOIN tbl_product_details pdop ON pdop.product_details_id = op.product_details_id
LEFT JOIN tbl_optic_make om ON op.optic_make_id = om.optic_make_id AND op.product_details_id = om.product_details_id
LEFT JOIN tbl_optic_model omod ON op.optic_model_id = omod.optic_model_id AND omod.optic_make_id = om.optic_make_id
LEFT JOIN tbl_optic_magnification omag ON omag.optic_magnification_id = op.optic_magnification_id
LEFT JOIN tbl_condition optcon ON op.condition_id = optcon.condition_id
LEFT JOIN tbl_optics opa ON opa.optic_id = a.optic_id AND a.gun_id is null
LEFT JOIN tbl_product_details pdopa ON pdopa.product_details_id = opa.product_details_id
LEFT JOIN tbl_optic_make oma ON opa.optic_make_id = oma.optic_make_id AND opa.product_details_id = oma.product_details_id
LEFT JOIN tbl_optic_model omoda ON opa.optic_model_id = omoda.optic_model_id AND omoda.optic_make_id = oma.optic_make_id
LEFT JOIN tbl_optic_magnification omaga ON omaga.optic_magnification_id = opa.optic_magnification_id
LEFT JOIN tbl_condition optcona ON opa.condition_id = optcona.condition_id
ORDER BY
e.entity_id,
a.advert_id) information_view
WHERE
CASE WHEN #product_type_id = ''
THEN information_view.product_type_id = information_view.product_type_id
ELSE information_view.product_type_id IN (select * from tm_product_type_id)end;
END
I have bellow query but has problem
set #lang = "en";
SELECT
COUNT(*) AS total_of_user,
COUNT(*) AS "total_of_user_#lang",
src.district AS district_name,
src.district AS "district_name_#lang"
FROM users LEFT JOIN (
SELECT
d.district_code,
d.name_en AS district,
p.name_en AS province_name,
p.`province_code`
FROM
provinces AS p LEFT JOIN districts AS d ON p.province_code = d.province_code
WHERE
p.province_code = '01'
) AS src ON src.district_code = users.district_code
WHERE
users.district_code IS NOT NULL AND
users.district_code <> '' AND
users.province_code = '01'
GROUP BY users.district_code
If I remove " from query the never run, but above query run and result came as district_name_#lang but I need the column name to be as district_name_en.
For any help thanks.
You would need to use dynamic SQL for this:
set #lang = 'en';
set #sql = '
SELECT COUNT(*) AS total_of_user,
COUNT(*) AS total_of_user_#lang,
src.district AS district_name,
src.district AS district_name_#lang
FROM users LEFT JOIN
(SELECT d.district_code, d.name_en AS district, p.name_en AS province_name, p.`province_code`
FROM provinces p LEFT JOIN
districts d
ON p.province_code = d.province_code
WHERE p.province_code = ''01''
) src
ON src.district_code = users.district_code
WHERE users.district_code IS NOT NULL AND
users.district_code <> '''' AND
users.province_code = ''01''
GROUP BY users.district_code';
set #sql = replace(#sql, '#en', #en);
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
Note: you cannot use parameters for column names or table names in a dynamic query.
UPDATED:
I am using pivot table for displaying column names as header as per my knowledge everything is fine but when i tried to add parameter I am getting error while
calling
call sp_schreport(1,2,'2014-10-04'); $$
AND WHEN I TRIED TO ADD
"select venue,'null' as first,'null' as second,'null' as third,'null' as fourth from sch_venue where campusid =campid and venueid NOT IN (select venueid from sch_taskassigned where assignedstatus=status AND (sdate BETWEEN taskstartdate AND taskenddate)) UNION"
along with that code getting error for union function both query column should be equal so that only i have used 'null' first etc..
CREATE PROCEDURE sp_schreport(IN campid int,IN status int,IN sdate datetime)
BEGIN
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(CASE WHEN t.session = ''',
t.session,
''' THEN d.department END) AS `',
tagname, '`'
)
) INTO #sql
FROM sch_sessions t;
SET #sql
= CONCAT('select venue,'null' as first,'null' as second,'null' as third,'null' as fourth from sch_venue where campusid =campid and venueid NOT IN (select venueid from sch_taskassigned where assignedstatus=status AND (sdate BETWEEN taskstartdate AND taskenddate))
UNION SELECT v.venueid, ', #sql, '
from sch_taskassigned p
left join sch_sessions t
on p.sid = t.sid inner join sch_venue v on p.venueid=v.venueid inner join sch_departments d where p.campusid=campid and p.assignedstatus=status and (sdate BETWEEN taskstartdate AND taskenddate) group by p.venueid');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
Kindly find out the mistakes in my procedure
The date variables are not passing correctly in the store procedure.
This portion returns a null
(CONVERT_TZ( (FROM_UNIXTIME(#fromDate/1000)),''UTC'', #timeZone) )AS startingDate,
(CONVERT_TZ( (FROM_UNIXTIME(#toDate/1000)),''UTC'', #timeZone) ) AS endingDate,
These dates are show null
l1.started BETWEEN #startDate AND #endDate
What I am I missing that the values are not passing into the query
CREATE PROCEDURE reportFreeCoolingTrackerTest (
IN fromDate varchar (50),
IN toDate varchar (50),
IN timeZone varchar (50))
BEGIN
DECLARE startDate varchar (50);
DECLARE endDate varchar (50);
DECLARE mylogID Int;
SET startDate = FROM_UNIXTIME(fromDate/1000);
SET endDate = FROM_UNIXTIME(toDate/1000);
SET mylogID = (SELECT logID FROM logs l WHERE l.details LIKE 'FCT%');
SET #tbl = CONCAT('log',mylogID);
set #q1 = CONCAT('SELECT
i.details,l1.item31985,l1.item31987,
((l1.item31985 - l1.item31987)*(time_to_sec(timediff(t2.completed, l1.completed)))) / 3600 AS kwDifference,
((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1))) AS cost,
(((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1)))
*(time_to_sec(timediff(t2.completed, l1.completed)) / 3600)) AS costT,
time_to_sec(timediff(t2.completed, l1.completed)) / 3600 AS coolingHours,
time_to_sec(timediff(#endDate, #startDate)) / 3600 AS totalTimeRange,
(CONVERT_TZ( (FROM_UNIXTIME(#fromDate/1000)),''UTC'', #timeZone) )AS startingDate,
(CONVERT_TZ( (FROM_UNIXTIME(#toDate/1000)),''UTC'', #timeZone) ) AS endingDate,DATABASE() AS databaseName,
CASE
when l1.activityId = t2.activityId THEN 1
ELSE 0
END AS errorCheck, t2.completed AS errorDay,a.scheduleType,#lgName,#mylogID
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN ', #tbl,' l1 ON a.activityId = l1.activityId ');
set #q2 = CONCAT(#q1, 'INNER JOIN ', #tbl);
SET #q3 = CONCAT(#q2, ' t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE ''%KW%''
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE ''%KW%''
WHERE i.itemID = "31985" AND l1.activityId = 1257
AND l1.started
BETWEEN #startDate
AND #endDate
ORDER BY l1.recordId,l1.started');
PREPARE stmt FROM #q3;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
There are numerous issues with your code. Here are major ones:
You're mixing procedure input parameters and local variables with user(session) variables. E.g. you have an input parameter fromDate but you refer to it in a query #fromDate which is user(session) variable and has nothing to do with the parameter. That's why you're getting NULL instead of actual values.
Instead of concatenating query string with variable values you just left variable names as part of string literal.
Date string literals (e.g. variables fromDate and startDate) should be quoted when you interpolate them in query string. Same goes to timeZone values.
In your query string you're referring to a #lgName variable, which most likely doesn't hold any value. And even if it does then instead of passing it through user(session) variable you should've done that through another procedure parameter.
This part
SET mylogID = (SELECT logID FROM logs l WHERE l.details LIKE 'FCT%');
should return the only value, otherwise it will break your code. Using LIKE can easily produce multiple rows. That being said either apply LIMIT 1 (or an aggregate function e.g. MIN() or MAX) or rewrite it using condition that based on a column(s) which has(have) a PK or UNIQE constraint.
fromDate, startDate, mylogID are local variables. But for some reason you use user variable #tbl to hold a table name value. Ditch it and just concatenate 'log' and mylogID value while you building your query string.
That being said your procedure might look something like
DELIMITER$$
CREATE PROCEDURE reportFreeCoolingTrackerTest (
IN fromDate VARCHAR (50),
IN toDate VARCHAR (50),
IN timeZone VARCHAR (50)
)
BEGIN
DECLARE startDate VARCHAR (50);
DECLARE endDate VARCHAR (50);
DECLARE mylogID INT;
SET startDate = FROM_UNIXTIME(fromDate/1000);
SET endDate = FROM_UNIXTIME(toDate/1000);
SET mylogID = 1; -- (SELECT logID FROM logs WHERE details LIKE 'FCT%' LIMIT 1);
SET #sql = NULL;
SET #sql = CONCAT(
'SELECT i.details,l1.item31985,l1.item31987,
((l1.item31985 - l1.item31987) * (time_to_sec(timediff(t2.completed, l1.completed)))) / 3600 AS kwDifference,
((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1))) AS cost,
(((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1)))
*(time_to_sec(timediff(t2.completed, l1.completed)) / 3600)) AS costT,
time_to_sec(timediff(t2.completed, l1.completed)) / 3600 AS coolingHours,
time_to_sec(timediff(''', endDate, ''', ''', startDate, ''')) / 3600 AS totalTimeRange,
CONVERT_TZ(''', startDate, ''', ''UTC'', ''', timeZone, ''') AS startingDate,
CONVERT_TZ(''', endDate, ''', ''UTC'', ''', timeZone, ''') AS endingDate,
DATABASE() AS databaseName,
CASE WHEN l1.activityId = t2.activityId THEN 1 ELSE 0 END AS errorCheck,
t2.completed AS errorDay,
a.scheduleType,
#lgName,
', mylogID, '
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN log', mylogID, ' l1 ON a.activityId = l1.activityId
INNER JOIN log', mylogID, ' t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE ''%KW%''
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE ''%KW%''
WHERE i.itemID = 31985 AND l1.activityId = 1257
AND l1.started BETWEEN ''', startDate, ''' AND ''', endDate, '''
ORDER BY l1.recordId,l1.started');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
Here is SQLFiddle demo that shows the final query string instead of executing it
I am trying to call one stored procedure withing another - using an if statement.
I am getting an error so I believe that I have something out of sequence
CREATE PROCEDURE reportFreeCoolingTrackerCalls (
IN fromDate varchar (50),
IN toDate varchar (50),
IN timeZone varchar (50))
BEGIN
DECLARE startDate varchar (50);
DECLARE endDate varchar (50);
DECLARE mylogID Int;
SET startDate = FROM_UNIXTIME(fromDate/1000);
SET endDate = FROM_UNIXTIME(toDate/1000);
IF (l1.activityId = t2.activityId)
THEN CALL reportFreeCoolingTrackerError (
fromDate,
toDate,
timeZone );
ELSEIF (l1.activityId != t2.activityId)
THEN CALL reportFreeCoolingTracker (
fromDate,
toDate,
timeZone );
END IF;
SELECT l1.activityId,t2.activityId
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN log1644 l1 ON a.activityId = l1.activityId
INNER JOIN log1644 t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE '%KW%'
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE '%KW%'
WHERE i.itemID = "31985" AND l1.activityId = 1257
AND l1.started
BETWEEN startDate
AND endDate
ORDER BY l1.recordId,l1.started;
END //
DELIMITER ;
ERROR
Unknown table 'l1' in field list
I think this code is causing the trouble for you:
IF (l1.activityId = t2.activityId) --Here l1 and t2 are not known
THEN CALL reportFreeCoolingTrackerError (
fromDate,
toDate,
timeZone );
ELSEIF (l1.activityId != t2.activityId) --Here l1 and t2 are not known
THEN CALL reportFreeCoolingTracker (
fromDate,
toDate,
timeZone );
END IF;
as in this line l1 is not known. Similarly t2 is also not known
Table aliases (such as INNER JOIN log1644 l1 ON... are only visible in the statement (in your case a SELECT) that contains them.
You'll need to refer to the full table name outside of that select.
As for the logic.... you'll need to populate the values you need in the SP call by using a select, and populating them into variables. Alternatively, use a select subquery in the call itself, but that would be a maintenance headache!