Oracle Missing Right Parenthesis - sql

Here is my query:
SELECT * FROM Auta WHERE SUBSTR(spz, 1, 2) =
(SELECT SUBSTR(spz, 1, 2) FROM Auta WHERE typ = 'BMW' AND specifikacia_typu = 'Z1' LIMIT 1);
And when I run it I get this error:
ORA-00907: missing right parenthesis
I'm getting a little desperate, I've already tried adding parentheses everywhere in the query and I still get the error? There are 3 left and 3 right parentheses in the query so everything should be all right.

The LIMIT clause doesn't exist in Oracle. Instead you would use rownum:
SELECT *
FROM Auta
WHERE SUBSTR(spz, 1, 2) = (SELECT SUBSTR(spz, 1, 2)
FROM Auta
WHERE typ = 'BMW'
AND specifikacia_typu = 'Z1'
AND ROWNUM = 1);

What's that "LIMIT 1" for? I don't believe that's correct Oracle syntax. If you're trying to limit the output to one row, use:
WHERE rownum = 1

LIMIT 1 is a MySQLism, as far as I know.
SELECT *
FROM Auta
WHERE SUBSTR(spz, 1, 2) =
(SELECT SUBSTR(spz, 1, 2)
FROM Auta
WHERE typ = 'BMW'
AND specifikacia_typu = 'Z1'
AND ROWNUM = 1);
...should give you the expected results

Related

Regular Expression

I FOUND MY MISTAKE!!! This is wrong CASE WHEN regexp_substr(artikel.abez1,'[^/]*$') AS download,
I just deleted 'Case when' and it works! Thank you everyone! :)
I have this data:
DE-Internet-LTE
AE-Internet-Ethernet-10M/30M
How can I get only the value "10M"? and if there's none, I want it to return to null.
I used this query:
regexp_substr(artikel.abez1,'[^-/]*$') AS upload
On the second row, it gives the result "10M" but on the first row it return to "LTE" instead of "null".
I'm using SQL Tool 1.8 b38.
UPDATE:
My full query:
`
SELECT DISTINCT artikel.artnr1, L1.lfnr1 AS lfnr, L1.name1 AS lf_name,
artikel.abez1, regexp_substr(artikel.abez1,'(.?){1}(.?)-', 1, 1, '',
2) AS land, regexp_substr(artikel.abez1,'(.?-){1}(.?)-', 1, 1, '',
2) AS Technologie, CASE WHEN
regexp_substr(artikel.abez1,'(.?-){2}(.?)-', 1, 1, '', 2) IS NULL
THEN regexp_substr(artikel.abez1,'[^-]$') ELSE
regexp_substr(artikel.abez1,'(.?-){2}(.?)-', 1, 1, '', 2) END AS
Topologie, regexp_substr(regexp_substr(artikel.abez1,
'([^-/]+)/[^-/]+$'), '^[^-/]+') AS upload, CASE WHEN
regexp_substr(artikel.abez1,'[^/]$') AS download,
bestanfragepos.preis / bestanfrage.bwkurs, 'Anfrage' AS Art,
To_Char(bestanfrage.lfdanfrage), bestanfrage.anfragedatum, CASE WHEN
InStr(angaufgut.reserve1, '.') > 1 THEN Months_Between(
bestanfrage.anfragedatum, To_Date(angaufgut.reserve1)) ELSE
To_Number(angaufgut.reserve1) end AS Laufzeit FROM artikel inner join
modell ON modell.lfdnr = artikel.lfdmodnr left join bestanfragepos ON
artikel.lfdnr = bestanfragepos.lfdartnr left join bestanfrage ON
bestanfragepos.lfdanfrage = bestanfrage.lfdanfrage left join lieferant
L1 ON L1.liefnr = bestanfrage.lfdliefnr left JOIN angaufgut ON
bestanfragepos.lfdangaufgutnr = angaufgut.lfdnr WHERE Lower(modcode)
LIKE 'ac%' AND Lower(abez1) NOT LIKE 'cust%' and artikel.mandant = 1
AND bestanfragepos.preis != 0 ORDER BY abez1 /
`
it gives error ora-00920 invalid relational operator.
It only worked on a single data when I used this:
SELECT regexp_substr(regexp_substr(artikelbez, '([^-/]+)/[^-/]+$'), '^[^-/]+') FROM nag_reporting_leitungspreise WHERE art = 'Vertrag' AND REF = 3791
Your code returns 30M. If you really want 10M, then this should do what you want:
select regexp_substr(regexp_substr(t.abez1, '([^-/]+)/[^-/]+$'), '^[^-/]+') AS upload
from t;
Here is a db<>fiddle.
with t(str) as (
select * from table(ku$_vcnt(
'DE-Internet-LTE',
'AE-Internet-Ethernet-10M/30M',
'AE-Internet-Ethernet-20m/40m',
'AE-Internet-Ethernet-300M/500M',
'AE-Internet-Ethernet-4000k/600k',
'AE-Internet-Ethernet-200M'
))
)
select
str,
regexp_substr(str, '(\d+(k|m))(/\d+(k|m))?',1,1,'i',1) upload,
regexp_substr(str, '/(\d+(k|m))',1,1,'i',1) download
from t;
Results:
STR UPLOAD DOWNLOAD
----------------------------------- ------- --------
DE-Internet-LTE
AE-Internet-Ethernet-10M/30M 10M 30M
AE-Internet-Ethernet-20m/40m 20m 40m
AE-Internet-Ethernet-300M/500M 300M 500M
AE-Internet-Ethernet-4000k/600k 4000k 600k
AE-Internet-Ethernet-200M 200M
Just have a look at the below solution:
with t(str) as
(
select column_value
from table(sys.odcivarchar2list(
'DE-Internet-LTE',
'AE-Internet-Ethernet-10M/30M',
'AE-Internet-Ethernet-20m/40m',
'AE-Internet-Ethernet-300M/500M',
'AE-Internet-Ethernet-4000k/600k',
'AE-Internet-Ethernet-200M'
))
)
select str,
regexp_substr(str, '-(\d+.*?)(/|$)',1,1,null,1) as upload,
regexp_substr(str, '/(\d+.*?)$',1,1,null,1) as download,
regexp_substr(regexp_substr(str, '([^-/]+)/[^-/]+$'), '^[^-/]+') as Gordan_Linoff_upload
from t;
Output:

cannot recognize input near 'SELECT' 'DISTINCT' '(' in expression specification -Hive

Trying to execute below query in hive. throwing exception cannot recognize input near 'SELECT' 'DISTINCT' '(' in expression specification. any help is appreciated.
SELECT DISTINCT (FISCAL_QUARTER_START_DATE)
FROM TEST_STAGE.TEST_TABLE
WHERE FISCAL_YEAR_ID =
(SELECT FISCAL_YEAR_ID
FROM TEST_STAGE.TEST_TABLE
WHERE CALENDAR_DATE = FROM_UNIXTIME (UNIX_TIMESTAMP ()))
AND SUBSTR (FISCAL_QUARTER_NAME, 0, 2) =
(SELECT SUBSTR (FISCAL_QUARTER_NAME, 0, 2)
FROM TEST_STAGE.TEST_TABLE
WHERE CALENDAR_DATE = FROM_UNIXTIME (UNIX_TIMESTAMP ()))
Thanks
Use proper table aliases and IN clause instead of = for sub-queries.
SELECT DISTINCT (t1.FISCAL_QUARTER_START_DATE)
FROM TEST_STAGE.TEST_TABLE t1
WHERE t1.FISCAL_YEAR_ID IN (
SELECT t2.FISCAL_YEAR_ID
FROM TEST_STAGE.TEST_TABLE t2
WHERE t2.CALENDAR_DATE = FROM_UNIXTIME(UNIX_TIMESTAMP())
)
AND SUBSTR(t1.FISCAL_QUARTER_NAME, 0, 2) IN (
SELECT SUBSTR(t3.FISCAL_QUARTER_NAME, 0, 2)
FROM TEST_STAGE.TEST_TABLE t3
WHERE t3.CALENDAR_DATE = FROM_UNIXTIME(UNIX_TIMESTAMP())
);
I think your query is equivalent and could be converted to a single sub-query with EXISTS.
SELECT DISTINCT t1.FISCAL_QUARTER_START_DATE
FROM TEST_STAGE.TEST_TABLE t1
WHERE EXISTS (
SELECT 1
FROM TEST_STAGE.TEST_TABLE t2
WHERE SUBSTR(t1.FISCAL_QUARTER_NAME, 0, 2) = SUBSTR(t2.FISCAL_QUARTER_NAME, 0, 2)
AND t1.FISCAL_YEAR_ID = t2.FISCAL_YEAR_ID
AND t1.CALENDAR_DATE = FROM_UNIXTIME(UNIX_TIMESTAMP())
);

How to convert below query from Oracle to Postgres having connect by?

I am converting my application DB from oracle to postgres. I am stuck on a function having connect by syntax. Below is the Oracle query.
PROCEDURE Get_Report_Data(parm_Billing_Month VARCHAR2, OUT Ref_Cur) IS
BEGIN
OPEN p_Data FOR
SELECT CASE
WHEN Id = 1 THEN
'Amount < 10000'
WHEN Id = 2 THEN
'10000-15000'
WHEN Id = 3 THEN
'15000-20000'
ELSE
'Amount > 20000'
END "Range",
SUM(Nvl(N1, 0)) N1,
SUM(Nvl(N2, 0)) N2,
SUM(Nvl(C1, 0)) C1,
SUM(Nvl(C2, 0)) C2,
SUM(Nvl(C3, 0)) C3,
SUM(Nvl(S1, 0)) S1,
SUM(Nvl(S2, 0)) S2,
COUNT(Site_Id) "No of Sites"
FROM (SELECT CASE
WHEN Nvl(Ed.Actual_Bill, 0) < 10000 THEN
1
WHEN Ed.Actual_Bill < 15000 THEN
2
WHEN Ed.Actual_Bill < 20000 THEN
3
ELSE
4
END Amount_Sort,
Decode(Er.Region_Id, 1, 1, 0) N1,
Decode(Er.Region_Id, 2, 1, 0) N2,
Decode(Er.Region_Id, 3, 1, 0) C1,
Decode(Er.Region_Id, 4, 1, 0) C2,
Decode(Er.Region_Id, 5, 1, 0) C3,
Decode(Er.Region_Id, 6, 1, 0) S1,
Decode(Er.Region_Id, 7, 1, 0) S2,
Ed.Site_Id
FROM Tbl_Details Ed,
Tbl_Site Es,
Tbl_Region Er,
Tbl_Subregion Esr
WHERE Ed.Site_Id = Es.Site_Id
AND Es.Subregion_Id = Esr.Subregion_Id
AND Esr.Region_Id = Er.Region_Id
AND Ed.Billing_Month_f = parm_Billing_Month) Data,
(SELECT Regexp_Substr('1,2,3,4,', '[^,]+', 1, Rownum) Id
FROM Dual
CONNECT BY Rownum <= Length('1,2,3,4,') -
Length(REPLACE('1,2,3,4,', ','))) All_Value
WHERE Data.Amount_Sort(+) = All_Value.Id
GROUP BY All_Value.Id
ORDER BY AVG(All_Value.Id);
END;
When I convert this query to postgres having some changes like Ref_Cur to refcursor and NVL to Coalesce function. I am still unable to resolve the connect by syntax. Some people suggested to use CTE's but I am unable to get it. Any help guys?
Edit
For random googlers below is the answer to my above problem. Special thanks to MTO.
WHERE Ed.Site_Id = Es.Site_Id
AND Es.Subregion_Id = Esr.Subregion_Id
AND Esr.Region_Id = Er.Region_Id
AND Ed.Billing_Month_f = p_Billing_Month) data
Right Outer Join (Select 1 as Id union All
Select 2 as Id union All
Select 3 as Id union All
Select 4 as Id) all_value
On data.Amount_Sort = all_value.Id
GROUP BY all_value.Id
ORDER BY AVG(all_value.Id);
The "generation" of IDs can be simplified in Postgres.
either use a values() clause:
Right Outer Join ( values (1,2,3,4) ) as all_value(id) On data.Amount_Sort = all_value.Id
or, if those are always a consecutive numbers, use generate_series():
Right Outer Join generate_series(1,4) as all_value(id) On data.Amount_Sort = all_value.Id
Since your hierarchical query appears to be using static strings, you can convert this:
SELECT Regexp_Substr('1,2,3,4,', '[^,]+', 1, Rownum) Id
FROM Dual
CONNECT BY Rownum <= Length('1,2,3,4,') - Length(REPLACE('1,2,3,4,', ',')
To:
SELECT 1 AS id FROM DUAL UNION ALL
SELECT 2 FROM DUAL UNION ALL
SELECT 3 FROM DUAL UNION ALL
SELECT 4 FROM DUAL
Which should then be simpler to convert to PostgreSQL.

Oracle SQL Group by Clause

I would like to write a sql to get top 5 table space storage metric. Below query gives the metric about all tbspaces. Appreciate if someone fine tune this to have only top N
SELECT
ts.tablespace_name AS TBNAME,
round((ts.tablespace_size/1024/1024),2) AS SIZE_MB,
round((ts.tablespace_used_size/1024/1024),2) AS USED_MB,
round(((ts.tablespace_size - ts.tablespace_used_size)/1024/1024),2) AS FREE_MB
FROM
mgmt$db_tablespaces ts,
(SELECT d.target_guid, d.tablespace_name, count(d.file_name) df_count,
sum(decode(d.autoextensible, 'YES', 1, 0)) auto_extend
FROM mgmt$db_datafiles d, mgmt$target t
WHERE t.target_guid = '<id>' AND
(t.target_type='rac_database' OR
(t.target_type='oracle_database' AND t.TYPE_QUALIFIER3 != 'RACINST')) AND
t.target_guid = d.target_guid
GROUP BY d.target_guid, d.tablespace_name) df
WHERE
ts.target_guid = df.target_guid AND
df.tablespace_name = ts.tablespace_name
ORDER BY ts.tablespace_size;`
Thanks
You can use the ROWNUM. Oracle applies rownum to the result after it has been returned.
You need to filter the result after it has been returned, so a subquery is required. You can also use RANK() function to get Top-N results.
SELECT
*
FROM
(
SELECT
ts.tablespace_name AS TBNAME,
round((ts.tablespace_size/1024/1024),2) AS SIZE_MB,
round((ts.tablespace_used_size/1024/1024),2) AS USED_MB,
round(((ts.tablespace_size - ts.tablespace_used_size)/1024/1024),2) AS FREE_MB
FROM
mgmt$db_tablespaces ts,
(SELECT d.target_guid, d.tablespace_name, count(d.file_name) df_count,
sum(decode(d.autoextensible, 'YES', 1, 0)) auto_extend
FROM mgmt$db_datafiles d, mgmt$target t
WHERE t.target_guid = '<id>' AND
(t.target_type='rac_database' OR
(t.target_type='oracle_database' AND t.TYPE_QUALIFIER3 != 'RACINST')) AND
t.target_guid = d.target_guid
GROUP BY d.target_guid, d.tablespace_name) df
WHERE
ts.target_guid = df.target_guid AND
df.tablespace_name = ts.tablespace_name
ORDER BY ts.tablespace_size
)
WHERE ROWNUM <= 5;

How to write a Sql statement without using union?

I have a sql statement like below. How can I add a single row(code = 0, desc = 1) to result of this sql statement without using union keyword? thanks.
select code, desc
from material
where material.ExpireDate ='2010/07/23'
You can always create a view for your table which itself uses UNION keyword
CREATE VIEW material_view AS SELECT code, desc, ExpireDate FROM material UNION SELECT '0', '1', NULL;
SELECT code, desc FROM material_view WHERE ExpireDate = '2010/07/23' OR code = '0';
WITH material AS
(
SELECT *
FROM
(VALUES (2, 'x', '2010/07/23'),
(3, 'y', '2009/01/01'),
(4, 'z', '2010/07/23')) vals (code, [desc], ExpireDate)
)
SELECT
COALESCE(m.code,x.code) AS code,
COALESCE(m.[desc],x.[desc]) AS [desc]
FROM material m
FULL OUTER JOIN (SELECT 0 AS code, '1' AS [desc] ) x ON 1=0
WHERE m.code IS NULL OR m.ExpireDate ='2010/07/23'
Gives
code desc
----------- ----
2 x
4 z
0 1
Since you don't want to use either a union or a view, I'd suggest adding a dummy row to the material table (with code = 0, desc = 1, and ExpireDate something that would never normally be selected - eg. 01 January 1900) - then use a query like the following:
select code, desc
from material
where material.ExpireDate ='2010/07/23' or
material.ExpireDate ='1900/01/01'
Normally, a Union would be my preferred option.