I need to change my query from Postgres to Presto but I am getting an error which I don't understand - "mismatched input '&'. Expecting: expression"
My SQL query-
SELECT sub.custID, sum(coalesce(cast(devicecount as INT), 0)) as devicecount, data_attr3 FROM(
SELECT custID, data_attr1 as devicecount, split_part(data_attr3, '-', 2) data_attr3,
RANK() OVER
(
PARTITION by custID
ORDER BY collected_on desc
) AS rownum
FROM tableA
) sub
WHERE rownum = 1 and string_to_array(data_attr3, ':') && '{0,1,2,4,5,16}'::text[] group by 1, 3
I am getting an error at the last line where I am using "&&" but the error goes if I remove it.
The error then is not recognizing string_to_array and it cant recognize ::text[] on the last line. Any help would be appreciated.
As always - documentation is your friend. Presto has quite different syntax for handling arrays, so depending on Presto version you can try next:
select cardinality( -- count elements in array
array_intersect( -- get arrays intersection
split('1:2:3', ':'), -- split string on ':' as string_to_array
array['0','1','2','4','5','16']) -- create varchar array
) > 0;
or
select arrays_overlap(
split('1:2:3', ':'),
array['0','1','2','4','5','16']
);
Output:
_col0
true
Related
This is my query:
SELECT
*,
CONCAT(
RIGHT( account_no, 4),
RIGHT( customer_id, 5 )
) AS "password for my diplomo"
FROM
account_info;
But I get this error:
Error: function left(bigint, integer) does not exist;
My table is:
CREATE TABLE account_info (
account_no bigint NOT NULL PRIMARY KEY,
customer_id varchar(...)
)
Postgres functions left and right expect their first argument be text.
So first cast account_no to type text and your query (a bit simplified) will work.
SELECT *,
right(account_no::text, 4) || right(customer_id, 5) as pfmd
FROM account_info;
Unrelated but the best practice under Postgres is to use type text instead of char or varchar.
You seem to be using a reference for T-SQL or JET Red SQL (for MS SQL Server and MS Access respectively) when you're actually using PostgreSQL which uses completely different functions (and syntax) for string/text processing.
This is the PostgreSQL v12 manual page for string functions and other syntax. You should read it.
As for making your query run on PostgreSQL, change it to this:
Convert account_no to a varchar type so you can use SUBSTRING with it.
I think it might work without it, but I don't like relying on implicit conversion, especially when localization/locale/culture issues might pop-up.
The LEFT and RIGHT functions for extracting substrings can be reimplemented like so:
LEFT( text, length ) == SUBSTRING( text FROM 0 FOR length )
RIGHT( text, length ) == SUBSTRING( text FROM CHAR_LENGTH( text ) - length )
And use || to concatenate text values together.
Like so:
SELECT
q.*,
(
SUBSTRING( q.account_no_text FROM CHAR_LENGTH( q.account_no_text ) - 4 )
||
SUBSTRING( q.customer_id FROM CHAR_LENGTH( q.customer_id ) - 5 )
) AS "password for my diplomo"
FROM
(
SELECT
ai.*,
ai.account_no::varchar(10) AS account_no_text
FROM
account_info AS ai
)
AS q
Here is a runnable DB-Fiddle.
Screenshot proof:
I have a column "employee_Id" in my Table "Employee".
employee_Id is having employee name and date of birth. For example :
Jason-21996 and Buttler
Please help me write a select query which returns Jason and Buttler as output.
This is the query I am trying :
select substring(employee_Id,1, LOCATE('-',employee_Id) - 1) as Emp_ID from Employee
I am seeing this error:
SQL Error [42815]: THE DATA TYPE, LENGTH, OR VALUE OF ARGUMENT 3 OF SUBSTRING IS INVALID. SQLCODE=-171, SQLSTATE=42815, DRIVER=4.9.78
Edit 1: As suggested by #Mark, I have edited the query as follows
select substring(employee_Id,1, LOCATE('-',employee_Id || '-') - 1) as Emp_ID from Employee
I am getting the same error. I tried to run the LOCATE and found that it is returning the index as 15 for Buttler as the column length is 15.
Run the following as is.
select substring(employee_Id, 1, LOCATE('-', employee_Id || '-') - 1) as Emp_ID
from
(
SELECT 'Jason-21996' FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Buttler' FROM SYSIBM.SYSDUMMY1
) Employee (employee_Id);
Does it work for you?
If your version of DB2 supports regular expressions, then a simple method is regexp_substr():
regexp_substr(employee_id, '^[^-]+')
Here is a db<>fiddle.
I have a column name "value" in table T with a long description of errors, it has here is an example of few
but it is also grabbing other rows which i don't need.
Please help?
This answers the original version of the question.
To filter the rows, use regexp_like(). I would suggest:
select t.*
from t
where regexp_like(value, '^An image has error at (1203|12345):')
I am guessing that the final colon is important for the matching.
Why can't you use the LIKE operator?
SELECT t.id, t.value, SUBSTR(t.value, 1, INSTR(t.value, ':')) short_value
FROM t
WHERE value LIKE 'An image has error at 1203:%'
OR value LIKE 'An image has error at 12345:%';
Perhaps your best option seems is a combination of a standard substr+instr to extract the desired value with a regexp_like to determine overall string t desirability overall string.
select substr(value, 1, instr(value, ':')-1 ) value
from d
where regexp_like (value,'An image has error at \d+:');
Although depending the exact requirement for leading test requirement and following numeric value perhaps just
select substr(value, 1, instr(value, ':')-1 ) value
from d
where instr(value, ':') > 1;
Finally you can stay with regexp_substr if you wish. However, Oracle's syntax for that is totally counter intuitive to use of regular expressions:
select value
from (select regexp_substr(value, '(.*):', 1, 1, 'i', 1) value
from d
)
where value is not null;
Demo
SELECT cast ( SUBSTRING ( CAST ("ProcessingDate" AS text), 5, 2 ) as integer),
COUNT(*) INTO resultValue1,resultValue2
FROM "DemoLogs"."Project"
WHERE "Addr" = 'Y' AND "ProcessingDate" >= 20160110
GROUP BY 1
ORDER BY 1;
In my database, the ProcessingDate is stored as YYYYMMDD. So, I am extracting its month from it.
This query is working fine if we remove the INTO clause but, I want to store the result to use it further.
So what should be the datatype of the variable resultValue1 and resultValue2 how to store the data(because data will be multiple).
As I am new to PostgreSQL I don't know how to do this can anybody help me out.
Here resultValue1 & resultValue2 will be tables not variables. you can group by using the column names.
Give some column alias names for both columns and group by using them.
You probably want this.
SELECT cast ( SUBSTRING ( cast ("ProcessingDate" as text),5 , 2 ) as
integer) AS resultValue1, COUNT(*) AS resultValue2
INTO <NewTable> --NewTable will be created with those two columns
FROM "DemoLogs"."Project"
-- conditions
Group By 1
-- other contitions/clauses
;
Kindly refer this INTO Documentation.
Hope this helps.
Try this:
SELECT cast ( SUBSTRING ( cast ("ProcessingDate" as text),5 , 2 ) as integer)resultValue1,
COUNT(*)resultValue2
INTO <Table Name>
FROM "DemoLogs"."Project"
WHERE "Addr" = 'Y'
AND "ProcessingDate" >= '20160110'
Group By 1
Order By 1;
Store the above query in the variable and remove that INTO clause from it.
So, query will be now :
query = SELECT cast ( SUBSTRING ( CAST ("ProcessingDate" AS text), 5, 2 ) as
integer),
COUNT(*)
FROM "DemoLogs"."Project"
WHERE "Addr" = 'Y' AND "ProcessingDate" >= 20160110
GROUP BY 1
ORDER BY 1;
Now declare result_data of type record and use in the following manner:
We are looping over result_data because it gives number of rows as output
and I have declared resultset of type text to store the result (as I needed further)
FOR result_data IN EXECUTE query
LOOP
RAISE NOTICE 'result : %',to_json(result_data);
resultset = resultset || to_json(result_data);
END LOOP;
select rptName
from RptTable
where rpt_id in (
select LEFT(Reports, NULLIF(LEN(Reports)-1,-1))
from repoAccess1
where uid = 'VIKRAM'
)
this is my sql query In which i have use the sub query to access selected field
in this sub query returns
select LEFT(Reports, NULLIF(LEN(Reports)-1,-1))
from repoAccess1
where uid = 'VIKRAM'
Returns
1,2
that means the query should be like
select rptName
from RptTable where rpt_id in (1,2)
But i m getting this error
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to numeric.
could anyone tell me ow to modify to get exact ans
It's a little hard to tell without the concrete table definitions, but I'm pretty sure you're trying to compare different data types to each other. If this is the case you can make use of the CAST or the CONVERT function, for example:
SELECT
[rptName]
FROM [RptTable]
WHERE [rpt_id] IN
(
SELECT
CONVERT(int, LEFT([Reports], NULLIF(LEN([Reports]) - 1, -1)))
FROM [repoAccess1]
WHERE [uid] = 'VIKRAM'
)
UPDATE: Since you have updated your question: The LEFT function returns results of either varchar or nvarchar data type. So the resulting query would be
SELECT
[rptName]
FROM [RptTable]
WHERE [rpt_id] IN('1', '2')
Please note the apostrophes (is this the correct term?) around the values. Since [rpt_id] seems to be of data type int the values cannot implicitly be converted. And that's where the aforementioned CAST or CONVERT come into play.
If I understand correctly, the subquery is returning a single row with a value of '1,2'. This is not a number, hence the error.
Before continuing, let me emphasize that storing values in comma delimited string is not the SQL-way of doing things. You should have one row per id, with proper types and foreign keys defined.
That said, sometimes we are stuck with other people's really bad design decisions. If this is the case, you can use LIKE:
select rptName
from RptTable r
where exists (select 1
from repoAccess1 a
where a.uid = 'VIKRAM' and
',' + a.reports + ',' like '%,' + cast(r.rpt_id as varchar(255)) + ',%'
);
select rptName
from RptTable
where rpt_id in (
select CAST(LEFT(Reports, NULLIF(LEN(Reports)-1,-1)) AS INT) as Val
from repoAccess1
where uid = 'VIKRAM'
)
Your query would work fine when (LEFT(Reports, NULLIF(LEN(Reports)-1,-1)) ) returns either 1 or 2 since SQL Server implicitly converts the varchar value to numeric.
It seems there might be a data issue. One of the data returned by LEFT function is non-numeric. In order to find that particular record you can use isnumeric function. Try like this,
SELECT rptName
FROM RptTable
WHERE rpt_id IN (
SELECT LEFT(Reports, NULLIF(LEN(Reports) - 1, - 1))
FROM repoAccess1
WHERE uid = 'VIKRAM'
AND ISNUMERIC(LEFT(Reports, NULLIF(LEN(Reports) - 1, - 1))) = 1
)