I'm having some trouble setting a user variable in MySQL and using it in the same query. I found one or two other questions similar to this, but couldn't get any of their solutions to work in my case.
Here's my query, stripped down a bit. I replaced values and names and stuff for simplicity, and removed some irrelevant parts, but left the basic structure for some context. Not really relevant but fyi I'm using CodeIgniter's active record class to build the query.
SELECT * FROM (things, (SELECT #exp_time := IF(5 < 10, X, Y) as var))
JOIN more_things ON ...
WHERE ...
AND #exp_time < UNIX_TIMESTAMP()
AND `#exp_time` > 1319180316
ORDER BY ...
LIMIT 1 ...
The error I'm getting is: "Every derived table must have its own alias."
Would really appreciate any assistance. Thanks!
Your actual error is because (as the error message explains) you haven't specified an alias for your derived table, and this is required in MySQL (even if you never use the alias anywhere else in your query).
SELECT *
FROM
(
things,
(SELECT #exp_time := IF(5 < 10, X, Y) as var) AS your_alias
)
...
However you don't need variables here. Now that your derived table actually has a name you have a way to refer to your value without needing to store it an a variable.
Related
I'm using Grafana to plot data from a MySQL datasource. Is it possible to, in a panel's query editor, use an IF ... THEN ... type statement. I would like to create a variable that I could put in the IF. I want the variable to be a condition, not necessarily to be used directly in the query.
For example:
//IN THE DATA SOURCE:
CREATE TABLE Example (Id INT, ANIMALS VARCHAR(15));
INSERT INTO Example VALUES (1,'Dog'), (2,'Fish'), (3,'Cat'), (4,'Lizard')
For a variable Test with values "Mammal',"Reptile", "Other":
//WHAT I'D LIKE IN GRAFANA QUERY EDITOR:
IF($Test = "Mammal") THEN
SELECT * FROM Example WHERE Id = 1 OR Id =3;
ELSE
SELECT * FROM Example WHERE Id = 2 OR Id =4;
END IF;
Is this kind of condition based query even possible? If so, what is the proper syntax to get it to work? Is there any way I can use Grafana variables to have a similar effect?
Use query. Query starts with SELECT keyword. Don't use any IF ELSE conditions before query, e.g.:
SELECT *
FROM Example
WHERE
Data IN ( ${variable:csv} )
This WHERE condition syntax will work with single value, multi value Grafana dashboard variables and also with All value (no custom All value, but blank=auto). Of course this condition is mainly for INT column types. STRING types may need different one (e.g. with LIKE and regexp matching).
Code all your logic (dependency on the dashboard variable) in the WHERE section. Use query inspector to see SQL which is generated and tweak it to correct SQL syntax.
Instead of an if, you can use or. It's really useful for conditionally checking variables:
select * from Example
where (Id in (1,3) or '$Test' != 'Mammal')
and (Id in (2,4) or '$Test' == 'Mammal')
I've already written the function, I'm trying to use FROM within an IF statement. The code below is written within a function.
IF myParameter IN (SELECT id FROM myTable) AND myTable.myType='Type A' THEN
Of course, it gives an error
Unknown table 'myTable'
when trying to execute the function.
EDIT: myParameter is an INT
Is this what you want?
IF myParameter IN (SELECT id FROM myTable WHERE myTable.myType = 'Type A') THEN
That is, move the condition to the subquery.
Typically, I'd use EXISTS for this kind of check:
IF EXISTS (SELECT * FROM myTable WHERE id = myParameter AND myType='Type A') THEN
EXISTS will stop processing at the first match, and despite requiring a SELECT for syntax reasons, doesn't actually create an intermediate result; IN generally processes the entire query within it, formulates a result set, and then checks the left hand argument of the IN against potentially everything in that result (it probably stops at the first match two, but it still had to assemble the entire result).
If myparameter is filtering on the table's primary key, it probably will not make much of a difference in this case; but it something to keep in mind in the more general sense.
I encounter some strange results in the following query :
SET #indi_id = 768;
SET #generations = 8;
SELECT num, sosa, seq, len, dernier, ful_ful_nom
FROM fullindi
LEFT JOIN lignee_new
ON ((ful_indi_id = dernier) AND (len BETWEEN 1 AND #generations))
RIGHT JOIN numbers
ON ((sosa = num) AND (premier = #indi_id))
WHERE num BETWEEN 1 AND pow(2, #generations)
GROUP BY num
ORDER BY num;
The result looks like this :
Why the row just before a full NULL one doesn't display the existing values 'sosa', 'len', 'dernier', ful_ful_nom') but only the 'seq' value (see rows 43 and 47 in this example) ?
What am I missing?
As requested, here are data :
table lignee_new :
table fullindi :
The problem is that MySQL does really dumb things when an Aggregate function is introduced, or a GROUP BY is included, but not all of the fields are in an Aggregate Function or your GROUP BY.
You are asking it to GROUP BY num but none of the other columns in your SELECT are included in the Group BY nor are they being aggregated with a function (SUM, MAX, MIN, AVG, etc..)
In any other RDBMS this query wouldn't run and would throw an error, but MySQL just carries on. It uses the logic to decide which value it should show for each field that isn't num by just grabbing the first value it finds in it's data storage which may be different between innoDB and whatever else folks use anymore.
My guess is that in your case you have more than one record in lignee_new that has a num of 43. Since you GROUP BY num and nothing else, it just grabs values randomly from your multiple records where num=43 and displays them... which is reasonable. By not including them in an aggregate function you are pretty much saying "I don't care what you display for these other fields, just bring something back" and so MySQL does.
Remove your GROUP BY clause completely and you'll see data that makes sense. Perhaps use WHERE to further filter your records to get rid of nulls or other things you don't need (don't use GROUP BY to filter).
I'm trying to create a View as following:
CREATE VIEW v_MyView
AS
SET #par_count := 0; -- XXX Working in SELECT, but not in a View !? XXX
SELECT
q1.day,
q1.count_per_day,
(#par_count := #par_count + q1.count_per_day) AS count_sum -- sums up count_per_day
FROM
(SELECT
DATE(registration_date_time_obj) AS day,
COUNT(Date(registration_date_time_obj)) AS count_per_day
FROM tbl_registration_data
GROUP BY day
ORDER BY day
) AS q1
;
The select statement itself works fine, just creating a view fails in MySQL since it doesn't accept user variables/parameters within it's declaration i guess.
Is there a way to still create this view with a workaround for the parameter?
Anyways, i'm able to create a similar procedure for the select statement, but that doesn't really solve the problem since i can't call the procedure in another select statement...
Thanks for your suggestions and solutions! (:
MySQL documentation is pretty clear that variables are not allowed:
The SELECT statement cannot refer to system variables or user-defined variables.
Within a stored program, the SELECT statement cannot refer to program parameters or local variables.
You can do what you want using a correlated subquery:
SELECT DATE(registration_date_time_obj) AS day,
COUNT(Date(registration_date_time_obj)) AS count_per_day,
(SELECT COUNT(*)
FROM tbl_registration_data rd2
WHERE rd2.registration_date_time_obj <= date_add(date(rd.registration_date_time_obj), interval 1 day)
FROM tbl_registration_data rd
GROUP BY day
ORDER BY day;
Please read the documentation on VIEWS >> https://dev.mysql.com/doc/refman/5.5/en/create-view.html
A view definition is subject to the following restrictions:
The SELECT statement cannot contain a subquery in the FROM clause.
The SELECT statement cannot refer to system variables or user-defined variables.
Within a stored program, the SELECT statement cannot refer to program
parameters or local variables.
The SELECT statement cannot refer to prepared statement parameters.
Any table or view referred to in the definition must exist. After the
view has been created, it is possible to drop a table or view that
the definition refers to. In this case, use of the view results in an
error. To check a view definition for problems of this kind, use the
CHECK TABLE statement.
The definition cannot refer to a TEMPORARY table, and you cannot
create a TEMPORARY view.
You cannot associate a trigger with a view.
Aliases for column names in the SELECT statement are checked against
the maximum column length of 64 characters (not the maximum alias
length of 256 characters).
This case is similar to: S.O Question; mySQL returns all rows when field=0, and the Accepted answer was a very simple trick, to souround the ZERO with single quotes
FROM:
SELECT * FROM table WHERE email=0
TO:
SELECT * FROM table WHERE email='0'
However, my case is slightly different in that my Query is something like:
SELECT * FROM table WHERE email=(
SELECT my_column_value FROM myTable WHERE my_column_value=0 AND user_id =15 LIMIT 1 )
Which in a sense, becomes like simply saying: SELECT * FROM table WHERE email=0, but now with a Second Query.
PLEASE NOTE: It is a MUST that I use the SECOND QUERY.
When I tried: SELECT * FROM table WHERE email='( SELECT my_column_value FROM myTable WHERE my_column_value=0 LIMIT 1 )' (Notice the Single Quotes on the second query)
MySql SCREAMED Errors near '(.
How can this be achieved
Any Suggestion is highly honored
EDIT1: For a visual perspective of the Query
See the STEN_TB here: http://snag.gy/Rq8dq.jpg
Now, the main aim is to get the sten_h where rawscore_h = 0;
The CURRENT QUERY as a whole.
SELECT sten_h
FROM sten_tb
WHERE rawscore_h = (
SELECT `for_print_stens_rowscore`
FROM `for_print_stens_tb`
WHERE `for_print_stens_student_id` =3
AND `for_print_stens_factor_name` = 'Factor H' )
The result of the Second Query can be any number including ZERO.
Any number from >=1 Works and returns a single corresponding value from sten_h. Only =0 does not Work, it returns all rows
That's the issue.
CORRECT ANSWER OR SOLUTION FOR THIS
Just in case someone ends up in this paradox, the Accepted answer has it all.
SEE STEN_TB: http://snag.gy/Rq8dq.jpg
SEE The desired Query result here: http://snag.gy/wa4yA.jpg
I believe your issue is with implicit datatype conversions. You can make those datatype conversions explicit, to gain control.
(The "trick" with wrapping a literal 0 in single quotes, that makes the literal a string literal, rather than a numeric.)
In the more general case, you can use a CAST or CONVERT function to explicitly specify a datatype conversion. You can use an expression in place of a column name, wherever you need to...
For example, to get the value returned by my_column_value to match the datatype of the email column, assuming email is character type, something like:
... email = (SELECT CONVERT(my_column_value,CHAR(255)) FROM myTable WHERE ...
or, to get the a literal integer value to be a string value:
... FROM myTable WHERE my_column_value = CONVERT(0,CHAR(30)) ...
If email and my_column_value are just indicating true or false then they should almost certainly be both BIT NOT NULL or other two-value type that your schema uses for booleans. (Your ORM may use a particular one.) Casting is frequently a hack made necessary by a poor design.
If it should be a particular user then you shouldn't use LIMIT because tables are unordered and that doesn't return a particular user. Explain in your question what your query is supposed to return including exactly what you mean by "15th".
(Having all those similar columns is bad design: rawscore_a, sten_a, rawscore_b, sten_b,... . Use a table with two columns: rawscore, sten.)