Postgresql 9.2 syntax issue - sql

I am trying to execute this query using Postgresql 9.2
WITH udetail as (select(regexp_split_to_array('user#domain', E'\\#+')))
select * from udetail[1];
Buy it gives me a syntax error near where the start of '['. This same query is working fine under version 9.3. So I'm wonder if there's an alternative way of writing the query to get the same result.

I think you are looking for something like this:
WITH udetail(x) as (
select(regexp_split_to_array('user#domain', E'\\#+')))
select x[1] from udetail;
I don't think you can index a table expression like udetail in your case. It is the column of the table expression that is of array type. Hence, you can use an array subscript number on the column, not on the table itself.
Demo here

You should use an alias either as the query parameter:
with udetail(arr) as (
select regexp_split_to_array('user#domain', E'\\#+')
)
select arr[1] from udetail;
or as column alias:
with udetail as (
select regexp_split_to_array('user#domain', E'\\#+') as arr
)
select arr[1] from udetail;
You can also do it without aliases:
with udetail as (
select regexp_split_to_array('user#domain', E'\\#+')
)
select regexp_split_to_array[1] from udetail;

Related

show columns in CTE returns an error - why?

I have a show columns query that works fine:
SHOW COLUMNS IN table
but it fails when trying to put it in a CTE, like this:
WITH columns_table AS (
SHOW COLUMNS IN table
)
SELECT * from columns_table
any ideas why and how to fix it?
Using RESULT_SCAN:
Returns the result set of a previous command (within 24 hours of when you executed the query) as if the result was a table. This is particularly useful if you want to process the output from any of the following:
SHOW or DESC[RIBE] command that you executed.
SHOW COLUMNS IN ...;
WITH columns_table AS (
SELECT *
FROM table(RESULT_SCAN(LAST_QUERY_ID()))
)
SELECT *
FROM columns_table;
CTE requires select clause and we cannot use SHOW COLUMN IN CTE's and as a alterative use INFORMATION_SCHEMA to retrieve metadata .Like below:
WITH columns_table AS (
Select * from INTL_DB.INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='CURRENCIES'
)
SELECT * from columns_table;

Escape square brackets in Oracle and PostgreSQL

I'm working on a project where the database could be an instance of oracle or Postgres.
I have the need to write a query with a like that work on both dbs.
The query works on a text column containing a JSON string, for example:
{"ruleName":"r2_an","divisionNameList":["div1"],"names":["name1"],"thirdTypeLabels":[],"secondTypeLabels":[],"firstTypeLabels":[]}
I need to select the lines with empty thirdTypeLabels.
select *
from my_table
where JSON like '%thirdTypeLabels%[]%';
On Oracle, for example, does not extract anything, even if in "my_table" there is more than one line matching.
The query is inside a Java software, using JDBC, because we need performace.
Have you any suggestion?
You should use a proper JSON parser otherwise there is no guarantee that %thirdTypeLabels%[]% will restrict the match of the empty array to the thirdTypeLabels key-value pair.
So for Oracle 18c you can use:
SELECT id,
thirdTypeLabelsCount
FROM mytable t
CROSS JOIN
JSON_TABLE(
t.json,
'$'
COLUMNS(
thirdTypeLabelsCount NUMBER PATH '$.thirdTypeLabels.size()'
)
)
WHERE thirdTypeLabelsCount = 0;
or
SELECT *
FROM mytable
WHERE JSON_EXISTS( json, '$ ? (#.thirdTypeLabels.size() == 0) ' )
db<>fiddle
For Postgres you have two choices to make this query work properly:
select *
from the_table
where jsonb_array_length(json::jsonb -> 'thirdTypeLabels') = 0;
Or - starting with Postgres 12 - using a JSON Path expression
select *
from the_table
where jsonb_path_exists(json::jsonb, '$.thirdTypeLabels.size() ? (# == 0)' );
Or use the same JSON path expression as in Oracle:
select *
from the_table
where jsonb_path_exists(json::jsonb, '$' ? (#.thirdTypeLabels.size() == 0)');
In Postgres you should also use a column defined as jsonb rather than text (or varchar)

SQL IN() multi-column condition with static right operand

I definitely know there is a right syntax for this but can't remember of find what it is: I need to do something like
SELECT
*
FROM
"table"
WHERE
("dep_date","ret_date") IN (('2019-10-10','2019-10-15'),('2019-10-11','2019-10-16'))
Except this syntax doesn't work. What is the correct syntax for defining a static multi-column lookup for the right operand of IN()?
You can try below way -
SELECT
*
FROM
"table"
WHERE ((dep_date='2019-10-10' and ret_date='2019-10-15') or
(dep_date='2019-10-11' and ret_date='2019-10-16'))
Use a subquery with UNION ALL after the IN clause:
SELECT
*
FROM
"table"
WHERE ("dep_date","ret_date") IN (
select '2019-10-10', '2019-10-15'
union all
select '2019-10-11','2019-10-16'
)
You can find more about Row Values in SQLite here: https://www.sqlite.org/rowvalue.html

Using REPLACE() Function Within a CONTAINS Predicate

I'm wondering if there's any way to use REPLACE() within a CONTAINS predicate.
For example, I know if I use:
SELECT * FROM table WHERE CONTAINS(column, 'searchWord')
It works with no problems; however, if I use:
SELECT * FROM table WHERE CONTAINS(REPLACE(column, 'oldPhrase', 'newPhrase'), 'searchWord')
It will give me an error because it is expecting a column instead of a string. If there's no way to do this, what's the best alternative?
Have you tried with a CTE ?
WITH r AS (
SELECT column0, column1, column2,
REPLACE(column, 'oldPhrase', 'newPhrase') col
FROM table
)
SELECT *
FROM r
WHERE CONTAINS(col, 'searchWord');

select where substring

SQL newbie here, but I can't find the solution to something that looks easy:
The following query does not seem to have a valid syntax (ORA-00904: invalid identifier), but its logic should be clear. How can I achieve this in a query that needs to be speedy?
SELECT * FROM table WHERE LEFT(column,4)="abcd"
For this purpose, you should use like rather than left(). First, Oracle doesn't support left() (you need substr() instead). Second, like can make use of indexes because the wildcard is not at the beginning of the string:
SELECT *
FROM table
WHERE column like 'abcd%';
Oracle and some other products have substr.
SELECT * FROM tablename WHERE substr(columnname, 1, 4) = 'abcd'
I.e. single quotes for string literals!
ANSI SQL has substring:
SELECT * FROM tablename WHERE substring(columnname from 1 for 4) = 'abcd'
And others have left:
SELECT * FROM tablename WHERE LEFT(columnname,4) = 'abcd'