Scala Slick sum() - postgresql

Currently I have a PostgreSQL query which calculates expression:
SELECT sum(timestamp2 - timestamp1 [some other math]) from <...> WHERE <...>.
Is there a way to do it with Slick? I tried to fetch raw data (login and logout) from database and process it, but this method is too expensive, so I need to process data on the database side.

This is how you do calculated columns
https://github.com/slick/slick/issues/1314
So in your case it will be
def ts(row: YourTableClass[_]) = row.timestamp2 -- row.timestamp1
Next you can do aggregation like shown in nmat's link

Related

Passing None into tokio postgres sql client query method

I am using tokio postgres in a Rust project where I have query parameters.
rows = client.query(QUERY, &[&input1, &input2.unwrap()]).await.expect("error");
where QUERY looks like this
QUERY: &str = "SELECT * FROM Table WHERE Name=$1 AND Address= COALESCE($2, Address);"
input2 is of type Rust option for which I will have to unwrap input2 before inserting it into the query method. Is there a way to make the query method handle "None" directly.
I can write conditional statements outside but that will make the source code unmanageable for the case where I have multiple optional queries.
You work with raw queries, tokio_postgres couldn't to manage None. In my experience best solution will write your own query builder.
You do not need to .unwrap() at all and can pass &input2 as-is. Option<T> implements ToSql where T: ToSql, if the value is None then it will pass NULL to the database:
let rows = client.query(
"SELECT * FROM Table WHERE Name=$1 AND Address=COALESCE($2, Address)",
&[&input1, &input2],
).await?;
Full working code that I tested on my local database is available here.

Get aggregate sum of difference of two dates in JOOQ

I am using JOOQ for writing SQL in my java code.I have following query written into the PostgreSQL database:'
Query: Fetches the total number of checked task and the total time taken to complete the tasks.
Total time for a task is calculated from table "workevents" by doing (endtime-starttime).But here I am fetching the total time spent on all the tasks.
with taskdata as (
select taskid from unittest.tasks
where projectname='test'and status='checked'
),
workevents as(
select (endtime-starttime) diff ,unittest.workevents.taskid as
workeventtaskid from unittest.workevents ,taskdata
where taskdata.taskid=unittest.workevents.taskid
)
select sum(workevents.diff),count(distinct workeventtaskid) from
workevents;
I have converted it into the jooQ AS below:
final String sql =
with(TASK_INFO_WRAPPER)
.as(select(TASK_ID).from(TASK_TABLE)
.where(PROJECT_NAME.eq(param()).and(TASK_STATUS.eq("checked"))))
.with(WORKEVENT_INFO_WRAPPER)
.as(select(TASK_END_TIME.sub(TASK_START_TIME).as("diff"),
WORKEVENT_TASK_ID.as("workeventtaskid"))
.from(WORKEVENT_TABLE, table(name(TASK_INFO_WRAPPER)))
.where("workeventinfo.taskid=taskinfo.taskid"))
.select().getSQL(ParamType.INDEXED);
But I am not able to get the aggregate sum of the "diff"(difference of the dates).Is there any function in JOOQ that can convert sql statement "select sum(workevents.diff)" into JOOQ.
I have tried sum(field) function but its giving compile time error because sum is used for numbers.
and Here I am calculating the accumulative sum of the difference of the two dates(diff).
All RDBMS behave subtly differently when implementing a date difference using the - operator, which is why it is generally recommended to use jOOQ's DSL.dateDiff() or DSL.timestampDiff() instead.
A side note on using WITH
WITH is often used to decompose a problem into smaller problems in SQL. But at some point, that decomposition leads to more complicated queries than necessary, as in your case. Especially when using jOOQ, it is often recommended to avoid common table expressions (WITH) or derived tables, not only because they're a bit more difficult to express in jOOQ, but also because they don't really add value to your query.
Your query could be written like this instead:
select
sum(e.endtime - e.starttime),
count(distinct e.taskid)
from unittest.tasks t
join unittest.workevents e on t.taskid = e.taskid
where t.projectname = 'test' and t.status = 'checked'
And that would obviously be quite easier to translate to jOOQ.

How to call 'like any' PostgreSQL function in JPQL

I have next issue:
I have list of names, based on which I want to filter.The problem is that I have not full names(Because I'm receiving them from ui), and I have, for example, this array= ['Joh', 'Michae'].
So, I want to filter based on this array.
I wrote query in PostgreSQL
select * from q_ob_person where name like any (array['%Хомяченко%', '%Вартопуз%']);
And I want to ask how to write JPQL query gor this.
Is there an option to call postgresql function like any from JPQL?
JPA 2.1 allows invocation of any SQL function using
FUNCTION(sqlFuncName, sqlArgs)
So you could likely do something like (note never tried this LIKE ANY you refer to, just play around with it)
FUNCTION("LIKE", FUNCTION("ANY", arrayField))
Obviously by invoking SQL functions specific to a particular RDBMS you lose database independence (in case that's of importance).

How are multiple result sets accessed in slick?

How does Slick handle a query that returns multiple result sets?
For example, if I wanted to retrieve information about a table using sp_help someTableName
Which would return a number of result sets. I can get the first result set, simply using scala.slick.jdbc.StaticQuery.queryNA[Tuple4[String, String, String,String]]("sp_help tblInbox_membership").first()
How do I get the second result set?
You must be using Sybase or maybe SqlServer.
I'm not familiar with Slick (yet), but the way to access subsequent ResultSets from a statement in JDBC is to call Statement.getMoreResults(), then if that succeeds Statement.getResultSet(). Slick gives you a Statement object with Session.withStatement, so you could at least use the JDBC api to get your resultsets, or feed the ResultSet to Slick if there is a way to do that.

How to optimize generic SQL to retrieve DDL information

I have a generic code that is used to retrieve DDL information from a Firebird database (FB2.1). It generates SQL code like
SELECT * FROM MyTable where 'c' <> 'c'
I cannot change this code. Actually, if that matters, it is inside Report Builder 10.
The fact is that some tables from my database are becoming a litle too populated (>1M records) and that query is starting to take too long to execute.
If I try to execute
SELECT * FROM MyTable where SomeIndexedField = SomeImpossibleValue
it will obviously use that index and run very quickly.
Well, it wouldn´t be that hard to the database find out that that is an impossible matcher and make some sort of optimization and avoid testing it against each row.
Is there any way to make my firebird database to optimize that search?
As the filter condition is a negative proposition (and also doesn't refer a column to search, but only a value to compare to another value), Firebird need to do a full table scan (without use any index) to confirm that aren't any record that meet your criteria.
If you can't change you need to wait for the upcoming 3.0 version, that will implement the Boolean data type, and therefore should start to evaluate "constant" fake comparisons in advance (maybe the client library will do this evaluation before send the statement to the server?).