Solved

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

Posted on 2013-12-17
7
251 Views
Last Modified: 2013-12-20
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
Comment
Question by:portlight
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
7 Comments
 
LVL 26

Expert Comment

by:tigin44
ID: 39726018
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
 

Author Comment

by:portlight
ID: 39726358
Will not compile
Gives me an error at PREPARE stmt FROM myQuery;
error: unexpected symbol myQuery
0
 
LVL 33

Accepted Solution

by:
snoyes_jw earned 500 total points
ID: 39726740
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
Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

 
LVL 33

Expert Comment

by:snoyes_jw
ID: 39726780
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
 

Author Comment

by:portlight
ID: 39730973
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
 

Author Closing Comment

by:portlight
ID: 39731091
While the query compiles and passes most of the data - any of the date calculations that are using variable are not passing
0
 
LVL 33

Expert Comment

by:snoyes_jw
ID: 39731762
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

The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I have been using r1soft Continuous Data Protection (http://www.r1soft.com/linux-cdp/) for many years now with the mySQL Addon and wanted to share a trick I have used several times. For those of us that don't have the luxury of using all transact…
This post contains step-by-step instructions for setting up alerting in Percona Monitoring and Management (PMM) using Grafana.
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

691 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question