How to add group_concat to hsqldb with distinct? - mysql

I am trying to add the group_concat function to hsqldb so that I can properly test a query as a unit/integration test. The query works fine in mysql, so I need it to work in hsqldb (hopefully).
// GROUP_CONCAT
jdbcTemplate.update("DROP FUNCTION GROUP_CONCAT IF EXISTS;");
jdbcTemplate.update(
"create aggregate function group_concat(in val varchar(100), in flag boolean, inout buffer varchar(1000), inout counter int) " +
" returns varchar(1000) " +
" contains sql " +
"begin atomic " +
" if flag then" +
" return buffer;" +
" else" +
" if val is null then return null; end if;" +
" if buffer is null then set buffer = ''; end if;" +
" if counter is null then set counter = 0; end if;" +
" if counter > 0 then set buffer = buffer || ','; end if;" +
" set buffer = buffer + val;" +
" set counter = counter + 1;" +
" return null;" +
" end if;" +
"end;"
);
Adding this aggregation function solves most of the problem. It will correctly behave like mysql's group_concat. However, what it won't do is let me use the distinct keyword like this:
group_concat(distinct column)
Is there any way to factor in the distinct keyword? Or do I rewrite the query to avoid the distinct keyword altogether?

HSQLDB has built-in GROUP_CONCAT and accepts DISTINCT.
http://hsqldb.org/doc/2.0/guide/dataaccess-chapt.html#dac_aggregate_funcs
At the moment you cannot add DISTINCT to a user-defined aggregate function, but this looks like an interesting feature to allow in the future.

Related

MySQL multiply a row by a variable

I am trying to multiply a row by a variable (calculated amount):
double servingsMultiplier = 1;
double servingSizeMultiplier = 1;
Calculate the values for "servingsMultiplier" and "servingSizeMultiplier".
String selectQry5 = ("SELECT ci_id, cr_id, ci_ingedient, (ci_amount*servingsMultiplier) AS ci_amount, " +
" (ci_unit*servingSizeMultiplier) AS ci_unit " +
" FROM at_cat_ingredient " +
" WHERE cr_id = ? " +
" ORDER BY ci_ingedient;");
The above works when I use a constant (e.g., 2); however, not when I use a variable. I get the error message:
"SQLException in recipePDF:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown
column 'servingsMultiplier' in 'field list'.
An identifier like servingsMultiplier inside the sql statement is not recognized as the value of the variable but as a column name, which of course does not exist.
Use ? placeholders for servingsMultiplier and servingSizeMultiplier in the statement and pass their values just like you pass the parameter in the WHERE clause:
String selectQry5 =
"SELECT ci_id, cr_id, ci_ingedient, " +
"(ci_amount * ?) AS ci_amount, " +
"(ci_unit * ?) AS ci_unit " +
"FROM at_cat_ingredient " +
"WHERE cr_id = ? " +
"ORDER BY ci_ingedient;";
If you want to use mysql variables, then add # before variable name.
SELECT ci_id, cr_id, ci_ingedient, (ci_amount*#servingsMultiplier) AS ci_amount,
(ci_unit*#servingSizeMultiplier) AS ci_unit
FROM at_cat_ingredient
WHERE cr_id = #id
ORDER BY ci_ingedient;

node-red, MySQL error

Get an error when writing to the database
The function for it:
var newMsg = { payload: msg.payload };
newMsg.topic="insert into MyTable (a,b,c,d,e,f,g) values (newMsg.payload)"
The incoming payload debug shows
payload: "B0:AC:A2:AC:07:F4","Ready","893901","860990","online","876","333"
The error I get from the database node (nore-red-node-mysql) is
"Error: ER_WRONG_VALUE_COUNT_ON_ROW: Column count doesn't match value
count at row 1"
The strange thing to me is that if I try a
newMsg.topic="insert into MyTable (a,b,c,d,e,f,g) values (\"B0:AC:A2:AC:07:F4\",\"Ready\",\"893901\",\"860990\",\"online\",\"876\",\"333\")"
it works perfectly...
Where is the trick?
There is no trick.
This is because the node-red-node-mysql and node-red-contrib-sqldbs nodes do not do any query substitution.
This means that what gets sent to the database is exactly what is in the msg.topic field. In this case that would have been:
insert into MyTable (a,b,c,d,e,f,g) values (newMsg.payload)
Which mysql will read as trying to pass a single value to a query expecting 7 values.
You will have to build the full query (and do your own variable escaping if needed) in a function node before passing the message to the database node.
at the end I solved it this way:
var data = msg.payload.split(",");
msg.payload = {};
msg.payload.a=data[0];
msg.payload.b=data[1];
msg.payload.c=data[2];
msg.payload.d=data[3];
msg.payload.e=data[4];
msg.payload.f=data[5];
msg.payload.g=data[6];
insert into MyTable (a,b,c,d,e,f,g) values ('" + data[0] + "','" + data[1] + "','" + data[2] + "','" + data[3] + "','" + data[4] + "','" + data[5] + "','" + data[6] + "')";
return msg;

Conversion from type 'DBNull' to type 'Double' is not valid

In my code I understand query getting null values and it throws this error. But since my query is little complex I don't understand how do I check for null values and avoid this error. Please help me to correct this query.
SELECT (SUM(charges) + SUM(behaviour) + SUM(admission) + SUM(properInformation) + SUM(hygine) + SUM(treatment))/(count(doctorID) * 6) AverageRating, COUNT(ID) RatingCount from ratings where doctorID = '" + doctorID + "'
If you want the query to not return NULL, you can just surround the expression with IFNULL to convert a possible NULL to 0, something like;
SELECT IFNULL((SUM(charges) + SUM(behaviour) + SUM(admission) +
SUM(properInformation) + SUM(hygine) + SUM(treatment))
/(count(doctorID) * 6), 0) AverageRating,
COUNT(ID) RatingCount
FROM ratings
WHERE doctorID = '" + doctorID + "'
If you definitely know your query returning null value correctly, then you can use try-catch block as below:
Try
Dim dt As DataTable = Me.GetData("SELECT (SUM(charges) + SUM(behaviour) + SUM(admission) + SUM(properInformation)
Catch ex As Exception
MsgBox("Error while fetching data" & vbCrLf & ex.Message)
End Try

Optimizing hive queries

I am trying to optimize hive query. I have partitioned and stored my base table as ORC file as shown below.
create table if not exists processed (
plc string,
direction string,
table int,
speed float,
time string
) PARTITIONED BY (time_id bigint) STORED AS ORC;
I am firing the below query on the above table (contains 500.000 records). The final result I get is stored as a json. The whole transaction takes about 35 secs. Is there a way wherein I can reduce this time. Or may be, someone could suggest me using a different framework instead of Hive. This is the query :
String finalQuery = "select plc,direction,AVG(speed) as speed ,COUNT(plc) as count,time_id from processed WHERE plc IN "
+ " "
+ "("
+ plcCSV
+ ")"
+ " " + " " + "AND" + " " + "time_id =" + " " + time_id + " "
+ "group by plc,direction,time_id";
First of all create an index on plc column and then try.

Delete query error for multiple records

I have a problem in this query:
string sqlString = "DELETE FROM [upload_news] WHERE (SELECT TOP " + no_of_recordss + " * FROM [upload_news] WHERE [country]='" + countryy.Text + "')";
Error Message :
Error: {"An expression of non-boolean type specified in a context
where a condition is expected, near ')'."}
How can i fix this ?
In the where clause you need a boolean expression.
Moreover, mysql doesn't support select top, you have to use limit instead and you can use it directly on delete
So your query should be:
delete from upload_news
where country=<SOME_COUNTRY> limit <NO_OF_RECORDS>
You have to replace values within "<>" with your desired values.
Or in your "strange" syntax:
string sqlString = "DELETE FROM [upload_news] WHERE [country]='" + countryy.Text + "' limit "+no_of_recordss;