Does hsqldb provide a function similar to listagg? - oracle

I am looking for a function (or a group of functions) in HSQLDB that does something similar to Oracle's LISTAGG.
I have this as part of a larger select and would like to keep the syntax as similar as possible in HSQLDB:
SELECT LISTAGG(owner_nm, ', ') WITHIN GROUP (ORDER BY owner_nm)
FROM OWNERSHIP WHERE FK_BIZ_ID = BIZ.BIZ_DATA_ID) AS CURRENT_OWNER
The point of this is that we're trying to use HSQLDB for remote work and Oracle for working on site, prod, etc so I want to change the DDLs as little as possible to achieve that.
Looking at ARRAY_AGG, it doesn't seem like it does anything similar (as far as being able to pull from a separate table like we're doing above with OWNERSHIP). Any suggestions for how I may accomplish this?

group_concat is probably what you are looking for:
http://www.hsqldb.org/doc/2.0/guide/dataaccess-chapt.html#dac_aggregate_funcs
Quote from the manual:
GROUP_CONCAT is a specialised function derived from ARRAY_AGG. This function computes the array in the same way as ARRAY_AGG, removes all the NULL elements, then returns a string that is a concatenation of the elements of the array

Related

Is there a way to get FIND_IN_SET functionality in MonetDB

I am migrating some of my workflows from MySQL to MonetDB.
One thing that has hampered my progress so far is the lack of FIND_IN_SET functionality in MonetDB:
> SELECT FIND_IN_SET('b', 'a,b,c,d');
2
I was relying on this functionality for converting domain definitions between two alignments.
Any idea how I could get this function in MonetDB with reasonable performance?
You could try using a regular expression. I recommended this to someone using MySQL who wanted to find more than one needle in a comma-delimited haystack, perhaps it could be adapted to MonetDB?
SELECT name FROM table WHERE CONCAT(',', DataID, ',') REGEXP ',(222|777|400),'

Dynamics AX 2012 Subquery in a View

AX allows you to enter basic SQL into View ranges. For example, in an AOT view's range, for the match value, you could enter (StatRepInterval.Name == 'Weekly'). This works nicely.
However, I need to do a more advanced lookup on a View, using a subquery. Can anyone suggest a way to do this?
This is what I would like to use, but I receive an error: "Query extended range failure: Syntax error near 34."
(StatRepInterval.Name == (SELECT FIRSTONLY StatRepInterval.Name FROM StatRepInterval WHERE StatRepInterval.PrintDirection == 1 ORDER BY StatRepInterval.Name DESC))
I've tried a lot of different variants of the subquery, from straight T-SQL to X++ SQL, but nothing seems to work.
Thanks for the help.
Sub-queries are not supported in query expressions.
This may be solved by using additional datasources with inner or outer joins as you observed.
See the spec and Axaptapedida on query expressions.
I found a way to do this. It isn't pretty, and I'm going to leave the question unanswered for a bit, should someone else have a more graceful solution.
Create a source View that contains all fields I wish to return, plus calculated fields that contain my subquery results.
Create a second View that uses the first as a data source, and applies all the necessary ranges.
Works pretty nicely.
Probably inefficient if there were large tables of data, but this is in a relatively small section of AX.

Need help translating returned data in Oracle query

Please keep in mind I am building a query in two phases here. The first phase is to get this to work with the existing query which is inefficient.
I am not good with PL/SQL at all, but I am learning slowly here.
I have this as a query:
SELECT LOGONID,FIRSTNAME,LASTNAME,ORGNAME
FROM WCSADMIN.USERREG UR,WCSADMIN.ADDRESS A
WHERE UR.USERS_ID = A.MEMBER_ID
AND A.ADDRESSTYPE IN('S','SB')
AND A.STATUS='P'
AND UR.STATUS='1'
AND (UPPER(LOGONID) LIKE UPPER('%cn=users%')
OR UPPER(LOGONID) LIKE UPPER('%o=Buyer A Organization%'))
AND UPPER(LOGONID) LIKE UPPER('uid=resourcereaper%')
AND rownum < 10; -- limits the rows back
Essentially the LOGONID field holds the LDAP string for logging on. The first characters in the field is uid=username,ou=......
I need to be able to carve that field down to just be "username". I think you can use the translate command, but I am unsure about how to trim off the uid= and everything (including) the first ",". Any insight would be greatly appreciated.
Josh
The translate command isn't the one you want - that does a character-for-character substitution.
You can use a combination of SUBSTR and INSTR to get the username, but the REGEXP_REPLACE is a little cleaner (my opinion of course). This will give you the uid value:
REGEXP_REPLACE(LogonID, '^uid=(.*?),.*$', '\1')
I'd explain the regular expression (and the \1) more, but I think the Oracle docs already do a much better job than I can.
Also, beware of the WHERE ROWNUM < 10. It's sometimes quirky (or at least appears so), and it won't work at all if you ORDER BY in your query. There's more info and a great explanation here. If you run into to trouble with ROWNUM you can fix it by putting ROWNUM into an outer query:
SELECT * FROM (
SELECT <your query>
) WHERE ROWNUM < 10
Something like this:
substr(LOGONID,
instr(LOGONID,'uid=')+4,
instr(LOGONID,',')-instr(LOGONID,'uid=')-4
)
This relies on the fact that there's always 'uid=' and a comma somewhere after it. If it's not the case, you'll need to handle exceptional cases as well. You could also use REGEXP_SUBSTR() if you want to be fancy.

Reversing a string using an index in Oracle

I have a table that has IDs and Strings and I need to be able to properly index for searching for the end of the strings. How we are currently handling it is copying the information into another table and reversing each string and indexing it normally. What I would like to do is use some kind of index that allows to search in reverse.
Example
Data:
F7421kFSD1234
d7421kFSD1235
F7541kFSD1236
d7421kFSD1234
F7421kFSD1235
b8765kFSD1235
d7421kFSD1234
The way our users usually input thier search is something along the lines of...
*1234
By reversing the strings (and the search string: 4321*) I could find what I am looking for without completely scanning the whole table. My question is: Is making a second table the best way of doing this?
Is there a way to reverse index?
Ive tried an index like this...
create index REVERSE_STR_IDX on TABLE(STRING) REVERSE;
but oracle doesn't seem to be using it according to the Explain Plan.
Thanks in advance for the help.
Update:
I did have a problem with unicode characters not being reversed correctly. The solution to this was casting them.
Example:
select REVERSE(cast(string AS varchar2(2000)))
from tbl
where id = 1
There is the myth that a reverse key index can be used for that, however, I've never seen that in action.
I would try a "manual" function based index.
CREATE INDEX REVERSE_STR_IDX on TBL(reverse(string));
SELECT *
FROM TBL
WHERE reverse(string) LIKE '4321%';

Is it possible to traverse rowtype fields in Oracle?

Say i have something like this:
somerecord SOMETABLE%ROWTYPE;
Is it possible to access the fields of somerecord with out knowing the fields names?
Something like somerecord[i] such that the order of fields would be the same as the column order in the table?
I have seen a few examples using dynamic sql but i was wondering if there is a cleaner way of doing this.
What i am trying to do is generate/get the DML (insert query) for a specific row in my table but i havent been able to find anything on this.
If there is another way of doing this i'd be happy to use but would also be very curious in knowing how to do the former part of this question - it's more versatile.
Thanks
This doesn't exactly answer the question you asked, but might get you the result you want...
You can query the USER_TAB_COLUMNS view (or the other similar *_TAB_COLUMN views) to get information like the column name (COLUMN_NAME), position (COLUMN_ID), and data type (DATA_TYPE) on the columns in a table (or a view) that you might use to generate DML.
You would still need to use dynamic SQL to execute the generated DML (or at least generate static SQL separately).
However, this approach won't work for identifying the columns in an arbitrary query (unless you create a view of it). If you need that, you might need to resort to DBMS_SQL (or other tools).
Hope this helps.
As far as I know there is no clean way of referencing record fields by their index.
However, if you have a lot of different kinds of updates of the same table each with its own column set to update, you might want to avoid dynamic sql and look in the direction of statically populating your record with values, and then issuing update someTable set row = someTableRecord where someTable.id = someTableRecord.id;.
This approach has it's own drawbacks, like, issuing an update to every, even unchanged column, and thus creating additional redo log data, but I believe it should be considered.

Resources