• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 270
  • Last Modified:

Concat query does not work when variable are in - how do I fix?

This code works fine. When I try to build it so that the table name (log1644) is dynamic I get errors. (see code below)
DELIMITER //
/*  Author: Jessie Brown     
    Date:   8/17/13 
    Notes:  Template Creation

    Comments: Comments created in the header area will NOT be stored in the database write
              Comments created AFTer the begin statement will be retained within the database write
*/

-- checks to see if stored procedure exists
-- if exists the procedure is dropped and recreated

DROP PROCEDURE IF EXISTS `reportFreeCoolingTracker`//

-- Creates new procedure

CREATE PROCEDURE reportFreeCoolingTracker (
        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);
            
SELECT g.groupId,
    g.name AS groupName,
    g1.parentId AS parentId1, 
    g1.name AS group1Name,
    g2.parentId AS parentId2, 
    g2.name AS group2Name,
    g3.parentId AS parentId3,
    g3.name AS group3Name,
    l.logId,l.name AS logName,
    l.ordering AS logOrder,
    a.activityId AS activityId,
    a.ordering AS activityOrder,
    a.name AS activityName,
    l1.recordId,
    l1.started, l1.completed,
    l1.userId,l1.note,
    u.name,
    TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
    substr(l.details, instr(l.details , ':' ) +1)AS charge,l.details,
    i.itemId,
    i.name AS itemName,
    i.itemType,
    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  

  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 ;

Open in new window


This code does not like how I am using the IN variables
DELIMITER //
/*  Author: Jessie Brown     
    Date:   8/17/13 
    Notes:  Template Creation

    Comments: Comments created in the header area will NOT be stored in the database write
              Comments created AFTer the begin statement will be retained within the database write
*/

-- checks to see if stored procedure exists
-- if exists the procedure is dropped and recreated

DROP PROCEDURE IF EXISTS `reportFreeCoolingTrackerTest`//

-- Creates new procedure

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 g.groupId,
    g.name AS groupName,
    g1.parentId AS parentId1, 
    g1.name AS group1Name,
    g2.parentId AS parentId2, 
    g2.name AS group2Name,
    g3.parentId AS parentId3,
    g3.name AS group3Name,
    l.logId,l.name AS logName,
    l.ordering AS logOrder,
    a.activityId AS activityId,
    a.ordering AS activityOrder,
    a.name AS activityName,
    l1.recordId,
    l1.started, l1.completed,
    l1.userId,l1.note,
    u.name,
    TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
    substr(l.details, instr(l.details , '':'' ) +1)AS charge,l.details,
    i.itemId,
    i.name AS itemName,
    i.itemType,
    i.details,l1.item31985,l1.item31987,
    (l1.item31985 - l1.item31987) 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 

  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); 
    set @q2 = CONCAT( @q1,' l1 ON a.activityId = l1.activityId 
      INNER JOIN ');
    set @q3 = CONCAT(@q2 , @tbl);
     SET @q4 = CONCAT(@q3,' 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.started');

      PREPARE stmt FROM @q4;
           
     EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
    END //

DELIMITER ;

Open in new window

0
portlight
Asked:
portlight
  • 3
  • 3
1 Solution
 
tigin44Commented:
try this

DELIMITER //
/*  Author: Jessie Brown    
    Date:   8/17/13
    Notes:  Template Creation

    Comments: Comments created in the header area will NOT be stored in the database write
              Comments created AFTer the begin statement will be retained within the database write
*/

-- checks to see if stored procedure exists
-- if exists the procedure is dropped and recreated

DROP PROCEDURE IF EXISTS `reportFreeCoolingTrackerTest`//

-- Creates new procedure

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;
                  DECLARE myQuery      varchar(2000);

             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);

SELECT myQuery = CONCAT('SELECT g.groupId,
    g.name AS groupName,
    g1.parentId AS parentId1,
    g1.name AS group1Name,
    g2.parentId AS parentId2,
    g2.name AS group2Name,
    g3.parentId AS parentId3,
    g3.name AS group3Name,
    l.logId,l.name AS logName,
    l.ordering AS logOrder,
    a.activityId AS activityId,
    a.ordering AS activityOrder,
    a.name AS activityName,
    l1.recordId,
    l1.started, l1.completed,
    l1.userId,l1.note,
    u.name,
    TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
    substr(l.details, instr(l.details , '':'' ) +1)AS charge,l.details,
    i.itemId,
    i.name AS itemName,
    i.itemType,
    i.details,l1.item31985,l1.item31987,
    (l1.item31985 - l1.item31987) 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

  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
      INNER JOIN ', @tbl,' 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.started');

      PREPARE stmt FROM myQuery;
           
     EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
    END //

DELIMITER ;
0
 
portlightAuthor Commented:
Will not compile
Gives me an error at PREPARE stmt FROM myQuery;
error: unexpected symbol myQuery
0
 
snoyes_jwCommented:
In MySQL, statements can only be prepared from string literals, or user variables. User variables always start with @ and do not have to be declared. So to solve that particular error, change:

SELECT myQuery =
to
SELECT @myQuery :=

and change:
PREPARE stmt FROM myQuery;
to
PREPARE stmt FROM @myQuery;

and you can drop the line:
DECLARE myQuery      varchar(2000);
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
snoyes_jwCommented:
To actually solve the problem, you have two choices:
- step outside the quotes around the variable names, just like you do for the table names. Since these are dates, you'll need to QUOTE() them:
 set @q1 = CONCAT('SELECT ... (FROM_UNIXTIME(', QUOTE(fromDate), '/1000...

Open in new window


- use '?' placeholders, and then execute the prepared statement with user variable parameters:
SET @fromDate = fromDate;
set @q1 = CONCAT('SELECT ... (FROM_UNIXTIME(?/1000...
PREPARE stmt FROM @q1;
EXECUTE stmt USING @fromDate;

Open in new window

0
 
portlightAuthor Commented:
I was able to get this to pull, however every place that uses the timeZone, toDate, fromDate, endDate and startDate return nulls. So I know I am not actually passing the input variables into the query correctly

SET @myQuery = CONCAT('SELECT g.groupId,
    g.name AS groupName,
    g1.parentId AS parentId1, 
    g1.name AS group1Name,
    g2.parentId AS parentId2, 
    g2.name AS group2Name,
    g3.parentId AS parentId3,
    g3.name AS group3Name,
    l.logId,l.name AS logName,
    l.ordering AS logOrder,
    a.activityId AS activityId,
    a.ordering AS activityOrder,
    a.name AS activityName,
    l1.recordId,
    l1.started, l1.completed,
    l1.userId,l1.note,
    u.name,
    TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
    substr(l.details, instr(l.details , '':'' ) +1)AS charge,l.details,
    i.itemId,
    i.name AS itemName,
    i.itemType,
    i.details,l1.item31985,l1.item31987,
    (l1.item31985 - l1.item31987) 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 

  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 
      INNER JOIN ', @tbl,' 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
      ORDER BY l1.started');

      PREPARE stmt FROM @myQuery;
     EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
    END //

Open in new window

0
 
portlightAuthor Commented:
While the query compiles and passes most of the data - any of the date calculations that are using variable are not passing
0
 
snoyes_jwCommented:
Your method will work if you assign those user variables to hold the same values as your parameters first:

SET @timeZone = timeZone;
SET @fromDate = fromDate;
etc.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now