Need help translating returned data in Oracle query - oracle

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.

Related

oracle - can I use contain and near with a clob? Need to speed up query

We have a query that takes 48 minutes to run a search on a clob. The query is written as if it is not a clob column and uses contains and near. This search for 3 words within a certain word distance from each other is important. I'm needing to speed this up and want to do an index on the clob, but don't know if that would work and don't fully understand how to do it. I found this from Tom Burleson
http://www.dba-oracle.com/t_clob_search_query.htm OR https://asktom.oracle.com/pls/apex/asktom.search?tag=oracle-text-contains-search-with-near-is-very-slow
, but can't figure out how to do it with contains and near to enable the search of 3 words withing a certain distance from each other.
current script:
SELECT clob_field
FROM clob_table
WHERE contains(clob_field,'NEAR (((QUICK),(FOX),(LAZY)),5)') > 0;
Want to use something like this if it will act like indexing:
SELECT clob_field
FROM clob_table
WHERE contains(dbms_lob.substr(clob_field,'near(((QUICK),(FOX),(LAZY)),5)')) > 0;
If not, I need to do indexing, but I don't quite understand how to use CTXCAT and CONTEXT (https://docs.oracle.com/cd/A91202_01/901_doc/text.901/a90122/ind4.htm). I also don't like what I read here that says that if one uses CTXCAT for indexing a clob you have to use CONTEXT, or something like that. It can't affect the other queries that are done on this field.
Thanks in advance!
Contains won't work unless it is globally indexed, so I had to index the field and then could get the original query working.

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.

Does hsqldb provide a function similar to listagg?

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

hibernate - using 'having' without group by clause in hql

im trying to run an hql query which aggragets (sum) number of transactions made on a specific account, i dont need a group by since my where clause has a specific account filter (where account = :account)
i do, however, want to return the aggregated value only if it is smaller/bigger than some given value.
when im adding 'having' after the where clause without 'group by' im getting an error -
unexpected token: having
in native sql i succeeded adding 'having' without group by
any ideas on how to make it work with hql?
thanks alot
The reason why databases don't let you mix grouped columns with non-grouped and non-aggregated ones is, that for non-grouped/non-aggregated columns it would have to choose one row's value per group, but doesn't know how to pick one.
If you don't care, then you could just leave it away and if it doesn't matter because they're all the same, you could group by them, too.
It is not hql, but if you have native query, then run it like:
Query query = session.createSQLQuery("select, *** ,... blah blah")
//set If you need
query.setParameter("myparam", "val");
List result = query.list();
In my eyes this is nonsense. 'having' is done for conditions on a 'group by' result. If you don't group, then it does not make much sense.
I would say HQL can't do it. Probably the Hibernate programmers didn't think of this case because they considered it as not important.
And anyway, you don't need it.
If it is a simple query, then you can decide in your java code if you want the result or if you don't need it.
If it is in a subselect, then you can solve the problem with a where condition in the main select.
If you think it is really necessary then your invited to give a more concrete example.

How do I query for when a field doesn't begin with a letter?

I'm tasked with adding an option to our search, which will return results where a given field doesn't begin with a letter of the alphabet. (The .StartsWith(letter) part wasn't so hard).
But I'm rather unsure about how to get the results that don't fall within the A-Z set, and equally hoping it generates some moderately efficient SQL underneath.
Any help appreciated - thanks.
In C# use the following construct, assuming db as a data context:
var query = from row in db.SomeTable
where !System.Data.Linq.SqlClient.SqlMethods.Like(row.SomeField, "[A-Z]%")
select row;
This is only supported in LINQ to SQL queries. All rules of the T-SQL LIKE operator apply.
You could also use less effective solution:
var query = from row in db.SomeTable
where row.SomeField[0] < 'A' || row.SomeField[0] > 'Z'
select row;
This gets translated into SUBSTRING, CAST, and UNICODE constructs.
Finally, you could use VB, where there appears to be a native support for the Like method.
Though SQL provides the ability to check a range of characters in a LIKE statement using bracket notation ([a-f]% for example), I haven't seen a linq to sql construct that supports this directly.
A couple thoughts:
First, if the result set is relatively small, you could do a .ToList() and filter in memory after the fact.
Alternatively, if you have the ability to change the data model, you could set up additional fields or tables to help index the data and improve the search.
--EDIT--
Made changes per Ruslan's comment below.
Well, I have no idea if this will work because I have never tried it and don't have a compiler nearby to try it, but the first thing I would try is
var query = from x in db.SomeTable
where x.SomeField != null &&
x.SomeField.Length >= 1 &&
x.SomeField.Substring(0, 1).All(c => !Char.IsLetter(c))
select x;
The possiblility exists that LINQ to SQL fails to convert this to SQL.

Resources