Complex MySQL cmd with JOINS and Counters doesnt work - mysql

I am working on this SQLFiddle and cant get the command working. Here the command:
SET #n := 1;
SET #start := '2013-07-22 10:00:01';
SET #end := '2013-07-22 10:00:02';
SET #register := 40001;
SELECT * FROM
(
SELECT
`realvalues`.`Timestamp`,
`realvalues`.`Value` * `register`.`Factor`,
#x := #x + 1 AS rank
FROM
`realvalues`,
(SELECT #x := 0) t
WHERE
`realvalues`.`Register` = register AND
`realvalues`.`Timestamp` BETWEEN start AND end
JOIN
`register`
ON
`register`.`DeviceID` = `realvalues`.`DeviceID` AND
`register`.`Register` = `realvalues`.`Register`
) a
WHERE
rank MOD ? = n
Does anybody know where the command fails? MySQL error reporting isnt very usefull.
[EDIT] The Value is now duplicated with Factor.

There are many many things wrong with your query. However, the error that is being reported in your fiddle is:
...check the manual that corresponds to your MySQL server version for the right syntax to use near 'BETWEEN start AND end JOIN register ON ...
Your syntax for BETWEEN is incorrect. There should be no IS token before BETWEEN. Correct syntax is:
<value> BETWEEN <lower-bound-inclusive> AND <upper-bound-inclusive>
Other problems include:
start, end, and n are not columns
register (in the WHERE clause) is ambiguous
You have a JOIN clause after a WHERE clause
You do not specify an alias for the second column of your derived table a (perhaps not necessary but may cause issues)
Use of a ? parameter without a way to specify a value (although this is a limitation of SQL Fiddle and not necessarily a problem with your SQL statement)

i dont see usage of #start and #end
EDIT: now it works !
sqlfiddle.com/#!2/6dc97/50

Related

JOOQ multiset throwing syntax exception

Recently moved to JOOQ 3.15.5 and tried the Multiset feature but it is throwing SQLSyntaxErrorException. Below is the query I wrote:
dslContext.select(
tableA.asterisk(),
multiset(
select(tableB.DELETED, tableB.VALUE)
.from(tableB)
.where(tableB.ORDER_ID.eq(tableA.ORDER_ID))
).as("bookingAdditions")
).from(tableA)
.where(tableA.BATCH_ID.greaterThan(batchId))
.fetchInto(BookingDto.class);
Here is the relations:
|tableA| 1 n |tableB|
| | --------------> | |
| | | |
-------- --------
(tableA) (tableB)
Here is the query that is being generated by JOOQ:
set #t = ##group_concat_max_len; set ##group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(json_merge_preserve('[]', concat('[', group_concat(json_array(`v0`, `v1`) separator ','), ']')), json_array()) from (select `tableb`.`deleted` as `v0`, `tableb`.`value` as `v1` from `db_name`.`booking_additions` as `tableb` where `tableb`.`order_id` = `tablea`.`order_id`) as `t`) as `bookingadditions` from `db_name`.`booking` as `tablea` where `tablea`.`batch_id` > 0; set ##group_concat_max_len = #t;
Here are exceptions:
org.jooq.exception.DataAccessException: SQL [set #t = ##group_concat_max_len; set ##group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(json_merge_preserve('[]', concat('[', group_concat(json_array(`v0`, `v1`) separator ','), ']')), json_array()) from (select `tableb`.`deleted` as `v0`, `tableb`.`value` as `v1` from `db_name`.`booking_additions` as `tableb` where `tableb`.`order_id` = `tablea`.`order_id`) as `t`) as `bookingadditions` from `db_name`.`booking` as `tablea` where `tablea`.`batch_id` > ?; set ##group_concat_max_len = #t;]; 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 'set ##group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(jso' at line 1
at org.jooq_3.15.5.MYSQL.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2988)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:639)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
at org.jooq.impl.AbstractResultQuery.fetchLazy(AbstractResultQuery.java:295)
at org.jooq.impl.AbstractResultQuery.fetchLazyNonAutoClosing(AbstractResultQuery.java:316)
at org.jooq.impl.SelectImpl.fetchLazyNonAutoClosing(SelectImpl.java:2866)
at org.jooq.impl.ResultQueryTrait.collect(ResultQueryTrait.java:357)
at org.jooq.impl.ResultQueryTrait.fetchInto(ResultQueryTrait.java:1423)
at com.company.BookingDAO.fetchBookings(BookingDAO.java:118)
at
I am using Mysql: 5.7. What am I doing wrong? Any hint?
jOOQ generates three SQL statements separated by semicolons when you use GROUP_CONCAT() in a query. Unfortunately, the default behavior of MySQL is to disallow multiple queries in a single request.
You have to change your JDBC connection options to include allowMultiQueries.
Read more about it here: https://blog.jooq.org/mysqls-allowmultiqueries-flag-with-jdbc-and-jooq/
Regarding the multiple statements
In addition to what Bill Karwin said, you could also specify the Settings.renderGroupConcatMaxLenSessionVariable to be false and increase your server's ##group_concat_max_len variable for your session or your server yourself.
jOOQ's default here is to assume it's easier to add the JDBC connection flag rather than change the server settings, but both approaches are viable.
Regarding correlated derived tables
This particular emulation requires support for correlated derived tables, which MySQL 5.7 doesn't support, see https://github.com/jOOQ/jOOQ/issues/12045. You're not going to get a correlated MULTISET expression to work on MySQL 5.7, but you could write an almost equivalent MULTISET_AGG expression, like this:
dslContext.select(
tableA.asterisk(),
multisetAgg(tableB.DELETED, tableB.VALUE).as("bookingAdditions")
).from(tableA)
.join(tableB).on(tableB.ORDER_ID.eq(tableA.ORDER_ID))
.where(tableA.BATCH_ID.greaterThan(batchId))
// You can group by the primary key, or tableA.fields() if you don't have a PK
.groupBy(tableA.ID)
.fetchInto(BookingDto.class);
Unlike MULTISET, MULTISET_AGG produces NULL values instead of empty lists in case you're left joining tableB, as is usual for SQL aggregate functions. You could then use coalesce(multisetAgg(...), multiset(...)) as a workaround.

SQL CREATE VIEW

I HAVE A QUERY LIKE THIS:
CREATE VIEW dashboard
AS
SET #prevValuepo := 0;
SET #prevValuefc := 0;
SELECT *,po-#prevValuepo AS selisihpo ,#prevValuepo:= po,forecast-#prevValuefc AS selisihfc ,#prevValuefc:= forecast
FROM view_t_dasboard WHERE tahun= '2020' ORDER BY bulan ASC
BUT WHY CAN'T CREATE TABLE VIEW
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 'SET #prevValuepo :=0, #prevValuefc :=0,
po-#prevValuepo AS selisihpo ,#prevValu' at line 4
You can't have these SET statemments inside the CREATE VIEW statement. Also, since the order of evaluation of expressions in the select clause is undefined, your query might not even do what you want consistently.
If you are running MySQL 8.0, I would recommend window functions instead of user-defined variables. I think the logic you want is:
create view dashboard as
select
t.*,
po - lag(po, 1, 0) over(order by bulan) as selisihpo,
forecast - lag(forecast, 1, 0) over(order by bulan) as selisihfc
from view_t_dasboard t
where tahun= '2020'

Create variable in SQL script before doing queries

I have the following snippet
select user_id into #selected_user from users where mail = 'mymail#gmail.com';
select * from kc_network_user where user_id = 'previous_id';
which I want to modify to be parametric. I found the following resources:
Using variables in SQL script
How to declare a variable in MySQL?
Declare variables - MySQL Workbench gives me an error with DECLARE
That's what I did:
select #user_mail := 'mymail#gmail.com'; #1
select #user_mail; #2
select user_id into #selected_user from user where mail = #user_mail; #3
select #selected_user;
select * from user_network where user_id = #selected_user; #4
In select #1 I tried also the following:
set #user_mail = 'mymail#gmail.com';
The select #2 returns the correct value, so the variable is initialized.
The select #3 returns the following error:
Error Code: 1267. Illegal mix of collations
(utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for
operation '='
While the select #4 runs correctly (if I set the mail parameter with the literal value).
What's the difference between those queries?
How can I set a variable before doing a query?
I don't understand why not simply
select *
from user_network
join user using (user_id)
where user.mail = 'mymail#gmail.com';
If you need to set mentioned variables additionally (but for what reason?) then use
select *, (#selected_user := user.user_id)
from user_network
join user using (user_id)
where user.mail = (#user_mail := 'mymail#gmail.com');

MySQL Workbench falsely claiming I have an error in my syntax

I have a stored procedure that determines and sets the next minute to review by getting the last reviewed timestamp and then determining what the lowest timestamp is after that.
The thing that bothers me about this is that while it works perfectly (so far), but MySQL workbench claims that I have 2 syntax errors:
CREATE DEFINER=`forex`#`%` PROCEDURE `set_next_minute`()
BEGIN
SET #next_minute = (
SELECT FLOOR(timestamp/60000) * 60
FROM tick
WHERE timestamp > (
(SELECT value
FROM setting
WHERE name = 'next_minute')
+ 60) * 1000
ORDER BY timestamp
LIMIT 1);
UPDATE setting
SET value = #next_minute
WHERE name = 'next_minute';
END
WHERE name = 'next_minute') missing 'closing parenthesis'
+ 60) * 1000 missing 'semicolon'
The funnier of these is that it says for the closing parenthesis it expects a closing parenthesis :-).
This is certainly a parser error and needs to be addressed. Can you file a bug report at http://bugs.mysql.com?

User variables - fighting syntax

Can anyone set my MySQL syntax straight please?
I am trying to set a user variable called "seconds" to equal the output of the query shown below (and it does work by it's self), but I am constantly geting "You have an error in your SQL syntax" errors.
SET #seconds=AVG(t2.epoch-t1.epoch)
FROM tmp_4045_metrics AS t1, tmp_4045_metrics AS t2
WHERE t1.seq+1 = t2.seq
I have tried SELECT AVG...., (SELECT AVG...), and quite a few others, but always the same error warning that my syntax is incorrect and never any clues to where it's incorrect.
Can anyone point me in the right direction?
Thanks,
Rich
If i remember correctly (and it works on MS SQL Server at work), this should do it:
Select #seconds=AVG(t2.epoch-t1.epoch)
FROM tmp_4045_metrics AS t1, tmp_4045_metrics AS t2
WHERE t1.seq+1 = t2.seq
Now the SELECT #seconds=... works error free - cracking :) and SELECT #seconds returns, but it's empty.
And I have triple checked the statement returns a value (300 seconds to be precise).
Back to the drawing board
Thanks for the suggestion though, better than I had achieved by myself.
In a SELECT statement, use the := assignment operator (not the = operator):
SELECT #seconds := AVG(t2.epoch-t1.epoch)
FROM tmp_4045_metrics AS t1, tmp_4045_metrics AS t2
WHERE t1.seq+1 = t2.seq