jOOQ - create value for field - sql

I have a Field Field<T>. I want to create a named value for that field, to be able to use it in a query. The name of the value should be the name of the field.
select value as field from ...
Is the the correct way to do it?
public <T> Field<T> namedValue(Field<T> field, T value) {
return DSL.val(value, field).as(field);
}
Although it works, I was wondering if there is a shorter way to do this. I might be pedantic here :).
update
I am creating the following construction:
UPADTE table SET x = alias.x, y = alias.y
FROM (SELECT constant value for x, table2.y FROM table2 WHERE ...) AS alias.
Let's simplify this to (for the sake of this example, to focus on the constant selection):
SELECT
FROM (SELECT constant value for x) AS alias.
First, I started with:
Select s1 = context.select(DSL.val("TEST"));
Select s2 = context.select(s1.fields()).from(s1);
This resulted in an incorrect query:
select "alias_66794930"."TEST" from (select 'TEST') as "alias_66794930"
(I am not really sure if this is correct behavior from jOOQ.)
So, I added an alias:
Select s1 = context.select(DSL.val("TEST").as(X));
Select s2 = context.select(s1.fields()).from(s1);
This resulted in:
select "alias_76324565"."x" from (select 'TEST' as "x") as "alias_76324565"
This works fine. Then, I ran into problems when the constant vale was null:
Select s1 = context.select(DSL.val(null).as(X));
Select s2 = context.select(s1.fields()).from(s1);
This resulted in:
select "alias_85795854"."x" from (select cast(? as varchar) as "x") as "alias_85795854"
1400 [localhost-startStop-1] TRACE org.jooq.impl.DefaultBinding - Binding variable 1 : null (class java.lang.Object)
This makes sense, the field type is not known. So I added the field (with its type) as following:
Select s1 = context.select(DSL.val(null, X).as(X));
Select s2 = context.select(s1.fields()).from(s1);
Binding is now correct:
1678 [localhost-startStop-1] TRACE org.jooq.impl.DefaultBinding - Binding variable 1 : null (class java.lang.String)
All done!

I don't think you can get much shorter than what you already have. I mean, your SQL reads:
value as field
And your Java/jOOQ code reads:
DSL.val(value, field).as(field)
You could of course static import DSL.val or DSL.*:
import static org.jooq.impl.DSL.*;
And then shorten things to:
val(value, field).as(field)
And if you're very sure about value's type, you don't need to coerce it to that of field
val(value).as(field)
Now, you definitely can't go any shorter, and there's no more need for your namedValue() function...

Related

Metabase - Field Filter as text

I have this SQL query:
select concept, count(*)
from annotation
where exists (select 1
from annotation a2
where a2.comment_commentid = annotation.comment_commentid and a2.concept = 'Fatigue'
)
group by concept;
And I want to replace 'Fatigue' with {{word}}, to do a filter widget, maping to the column from database.
I have the following error:
ERROR: syntax error at or near "=" Position: 307
What I need to change to aplly the filter? selecting the available words from that column?
With variable type as Text it works... But don't display all the available options, in filter, as variable type Field Filter do...
Thanks!
The outer annotation table needs an alias too. When in doubt, the inner scope always prevails whern resolving names, and the inner exists(...) query an an annotation name in scope, too)
[And the cause of your error is probably that the middleware gets confused]
select concept, count(*)
from annotation a1 -- <<-- HERE!
where exists (select 1
from annotation a2
where a2.comment_commentid = a1.comment_commentid and a2.concept = 'Fatigue'
)
group by concept;

How to write my clickhouse sql query correctly?

I have written a sql query:
WITH
type = "id" AND match(value, '*** ID WAS ACTIVATED ***') as id_activ
SELECT
multiIf(
id_activ, 'id_activ',
NULL) as case,
date,
value
FROM my.data.base
However it doesn't work. A problem occurs because of this part: match(value, '*** ID WAS ACTIVATED ***'). When i try this, it works perfectly:
WITH
type = "id" AND value LIKE '%*** ID WAS ACTIVATED ***%' as id_activ
SELECT
multiIf(
id_activ, 'id_activ',
NULL) as case,
date,
value
FROM my.data.base
Here is a full message with that pattern that I use in match:
*** ID WAS ACTIVATED *** : Values expired
How could i fix it and write query with match right?
Same thing with query which has square brackets in it:
WITH
type = "id" AND match(value, 'Values processed [NUMBERS]') as id_number
SELECT
multiIf(
id_number, 'id_number',
NULL) as case,
date,
value
FROM my.data.base
match() is matching regular expression
"Equivalent" to
LIKE '%*** ID WAS ACTIVATED ***%'
is
match(value, '.*\*\*\* ID WAS ACTIVATED \*\*\*.*')
https://regex101.com/r/XkRmEY/1

Checking against value in a STRING_TABLE in a WHERE clause

I have a procedure with the parameter IT_ATINN:
IMPORTING
REFERENCE(IT_ATINN) TYPE STRING_TABLE
IT_ATINN contains a list of characteristics.
I have the following code:
LOOP AT values_tab INTO DATA(value).
SELECT ( #value-INSTANCE ) AS CUOBJ
FROM IBSYMBOL
WHERE SYMBOL_ID = #value-SYMBOL_ID
AND ATINN ??? "<======== HERE ???
APPENDING TABLE #DATA(ibsymbol_tab).
ENDLOOP.
How can I check if ATINN (in the WHERE clause) is equal to any entry in IT_ATINN?
To achieve what you want (and I assume you want dynamic SELECT fields) you cannot use inline declarations here, both in LOOP and in SELECT:
The structure of the results set must be statically identifiable. The SELECT list and the FROM clause must be specified statically and host variables in the SELECT list must not be generic.
So either you use inline or use dynamics, not both.
Here is the snippet that illustrates Sandra good suggestion:
TYPES: BEGIN OF ty_value_tab,
instance TYPE char18,
symbol_id TYPE id,
END OF ty_value_tab.
DATA: it_atinn TYPE string_table.
DATA: rt_atinn TYPE RANGE OF atinn,
value TYPE ty_value_tab,
values_tab TYPE RANGE OF ty_value_tab,
ibsymbol_tab TYPE TABLE OF ibsymbol.
rt_atinn = VALUE #( FOR value_atinn IN it_atinn ( sign = 'I' option = 'EQ' low = value_atinn ) ).
APPEND VALUE ty_value_tab( instance = 'ATWRT' ) TO values_tab.
LOOP AT values_tab INTO value.
SELECT (value-instance)
FROM ibsymbol
WHERE symbol_id = #value-symbol_id
AND atinn IN #rt_atinn
APPENDING CORRESPONDING FIELDS OF TABLE #ibsymbol_tab.
ENDLOOP.
Overall, it makes no sense select ibsymbol in loop, 'cause it has only 8 fields, so you can easily collect all necessary fields from values_tab and pass them as dynamic fieldstring.
If you wanna use alias CUOBJ for your dynamic field you should add it like this:
LOOP AT values_tab INTO value.
DATA(aliased_value) = value-instance && ` AS cuobj `.
SELECT (aliased_value)
...
Remember, that your alias should exists among ibsymbol fields, otherwise in case of static ibsymbol_tab declaration this statement will throw a short dump.

Linq Query in VB

Good Day,
I am querying my database using Linq and I have run into a problem, the query searched a column for a search phrase and based on if the column has the phrase, it then returns the results, The query is below,
Dim pdb = New ProductDataContext()
Dim query =
From a In pdb.tblUSSeries
Join b In pdb.tblSizes_ On a.Series Equals b.Series
Where
a.Series.ToString().Equals(searchString) Or
b.Description.Contains(searchString) Or Not b.Description.Contains(Nothing)
Order By b.Series, b.OrderCode Ascending
Select New CustomSearch With
{
.Series = a.Series,
.SeriesDescription= a.Description,
.Coolant = a.Coolant,
.Material = a.Material,
.Standard = a.Standard,
.Surface = a.Surface,
.Type = a.Type,
.PointAngle = a.PointAngle,
.DiaRange = a.DiaRange,
.Shank = b.Shank,
.Flutes = b.Flutes,
.EDPNum = b.EDPNum,
.SizesDescription = b.Description,
.OrderCode = b.OrderCode
}
Return query
I think the problem is that, in the table certain rows are NULL, so when it is checking the column for the phrase and it encounters a row that is null it, breaks and returns this error,
The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
I have ran this query against another column that has all the rows populated with data and it returns the results ok.
So my question is how can I write it in VB to query the db with the supplied searchstring and return the results, when some of the rows in the columns have null values.
Any help would be great.
The exception occurs when you make the projection (i.e. select new CustomSearch)
And yes your trying to assign Null to some int property
(Not sure which one of your properties that is)
one of 2 choices :
1) Use nullalbe types for your properties (or just that one property).
2) project with an inline If ( ?? in C#) , I don't know VB so don't catch me on the syntax.
Taking Series just as an example i don't know if it's an int or if that's the problematic property
Select New CustomSearch With
{
.Series = If(a.Series Is Nothing,0, CInt(a.Series))
}
In C#
Select new CustomSearch
{
Series = a.Series ?? 0;
}

Return 0 if field is null in MySQL

In MySQL, is there a way to set the "total" fields to zero if they are NULL?
Here is what I have:
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT SUM(uop.price * uop.qty)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT SUM(upr.amount)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT SUM(uoli.amount)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;
The data comes out fine, except the NULL fields should be 0.
How can I return 0 for NULL in MySQL?
Use IFNULL:
IFNULL(expr1, 0)
From the documentation:
If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns expr2. IFNULL() returns a numeric or string value, depending on the context in which it is used.
You can use coalesce(column_name,0) instead of just column_name. The coalesce function returns the first non-NULL value in the list.
I should mention that per-row functions like this are usually problematic for scalability. If you think your database may get to be a decent size, it's often better to use extra columns and triggers to move the cost from the select to the insert/update.
This amortises the cost assuming your database is read more often than written (and most of them are).
None of the above answers were complete for me.
If your field is named field, so the selector should be the following one:
IFNULL(`field`,0) AS field
For example in a SELECT query:
SELECT IFNULL(`field`,0) AS field, `otherfield` FROM `mytable`
Hope this can help someone to not waste time.
You can try something like this
IFNULL(NULLIF(X, '' ), 0)
Attribute X is assumed to be empty if it is an empty String, so after that you can declare as a zero instead of last value. In another case, it would remain its original value.
Anyway, just to give another way to do that.
Yes IFNULL function will be working to achieve your desired result.
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT IFNULL(SUM(uop.price * uop.qty),0)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT IFNULL(SUM(upr.amount),0)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT IFNULL(SUM(uoli.amount),0)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;