DB2 count(*) over(partition by fieldname) giving -104 z/OS version 7 - sql

I have slimmed down the query to remove potential complications, in addition I have verified that the fields are correct. DB2 UDB zSeries V7 is my db2 version.
SELECT
STDINSTRCD,
COUNT(*) OVER(PARTITION BY STDINSTRCD),
CAST(STDINSTRDESC AS VARCHAR(1000)) AS INSTR,
C.STDINSTRSEQ,
1
FROM
SYST.SCC004 C
WHERE
C.STDINSTRCD = '098'
I have tried a subquery as well.
select
H2.FRSTSTDINSTRCD,
(select count(*) from SYST.scC004 Ci where '098'=Ci.STDINSTRCD) as cnt,
cast(STDINSTRDESC as varchar(1000)),
C.STDINSTRSEQ,
1
from SYST.scE4A00 H2
LEFT OUTER JOIN SYST.scC004 C
ON C.STDINSTRCD = H2.FRSTSTDINSTRCD
WHERE
H2.CTLENTYID='MCS'
AND H2.VCKVAL='12654'
AND H2.POKVAL='0198617S12 000 000'
The error is receive is om.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -104, SQLSTATE: 42601, SQLERRMC: (;, FROM INTO sqlcode sqlstate
-104 Illegal Symbol token.
42601 A character, token, or clause is invalid or missing.
Any advice? I have been unable to determine what syntax error I might me making.

are there any weird special characters in there that might not be printing?
http://www-01.ibm.com/support/docview.wss?uid=swg1IY43009
basically sounds like a weird cr/lf or special char? Any copy pasting from *nix to windows ?
Also, I'm not sure why you need partition by anyway? would a group by not accomplish your goal. (looks like your just counting number of rows that met your criteria)...
something like this for your first query?
SELECT
STDINSTRCD,
count(1) ,
CAST(STDINSTRDESC AS VARCHAR(1000)) AS INSTR,
C.STDINSTRSEQ,
1
FROM SYST.SCC004 C
WHERE C.STDINSTRCD = '098'
group by
STDINSTRCD,
CAST(STDINSTRDESC AS VARCHAR(1000)) AS INSTR,
C.STDINSTRSEQ,
1

Db2 Version 7 for z/OS does not support OLAP functions, or row_number(). You need to rewrite your query to avoid using such functions. They arrived in later Db2 versions. See also other people's tips on alternatives via this link.

Related

Oracle SQL sort by ternary operation

I'm trying to sort records in ORACLE SQL such that all strings that contain the phrase 'VENT' are sorted to the top, and the others are sorted by length.
Select D1.MENU_TEXT
from IMPRESSIONS_DEF D1
order by IFF(instr(D1.MENU_TEXT, 'VENT'),1, LENGTH(D1.MENU_TEXT));
I tried this, but it fails with "IFF" invalid identifier. I also tried
Select D1.MENU_TEXT, iff(D1.MENU_TEXT like '%VENT%', 1, 200) as k
from IMPRESSIONS_DEF D1
order by k + Length(D1.Menu_Text);
and it says "missing right parenthesis"
Use a case expression:
ORDER BY (CASE WHEN MENU_TEXT LIKE '%VENT%' THEN 1 ELSE 2 END),
LENGTH(D1.MENU_TEXT);
CASE is standard SQL. IIF() is bespoke SQL only used by a few databases.

Error with group by in DB2 - SQLSTATE 42803

I've got a SQL script and its failing. This is what it looks like:
SELECT P.SOORT,P.TYPEBETALING, P.MIDDELCODE, P.HOEVEELHEID, P.EENHEID, P.BEDRAG,P.MIDDEL
FROM DAAO01.BETALINGEN as A join
DAAO01.KLANTEN P
on p.KLANT_ID = 1
GROUP BY P.TYPEBETALING
ORDER BY P.TYPEBETALING
When I execute this I get an error:
COLUMN OR EXPRESSION IN THE SELECT LIST IS NOT VALID. SQLCODE=-122, SQLSTATE=42803, DRIVER=4.18.60
What am I doing wrong?
It is quite difficult to tell what you're trying to do without seeing your data.
But the error is saying that you have not specified how you are going to deal with the rest of the fields in your Group by aggregation:
P.SOORT, P.MIDDELCODE, P.HOEVEELHEID, P.EENHEID, P.BEDRAG, P.MIDDEL
If they're numbers, then you could sum them or take the avg etc.
If they're strings, then you either need to group by them or remove them from your selection.

How to convert this SAS code to SQL Server code?

SAS CODE:
data table1;
set table2;
_sep1 = findc(policynum,'/&,');
_count1 = countc(policynum,'/&,');
_sep2 = findc(policynum,'-');
_count2 = countc(policynum,'-');
_sep3 = findc(policynum,'_*');
_count3 = countc(policynum,'_*');
How can I convert this into a select statement like below:
select
*,
/*Code converted to SQL from above*/
from table2
For example I tried the below code:
select
*,
charindex('/&,',policynum) as _sep1,
LEN(policynum) - LEN(REPLACE(policynum,'/&,','')) as _count1
from table2
But I got a ERROR 42S02: Function 'CHARINDEX(UNKNOWN, VARCHAR)' does not exist. Unable to identify a function that satisfies that given argument types. You may need to add explicit typecasts.
Please note that the variable pol_no is: 'character varying(50) not null'.
I am running this on using Aginity Workbench for Netezza. I believe this is IBM.
Assuming Oracle based on CHARINDEX() this may work:
You need to apply it twice, once for each character and take the minimum to find the first occurrence.
There may be a better suited function within Oracle, but I don't know enough to suggest one.
select
*,
min(charindex('/',policynum), charindex('&', policynum)) as _sep1
from table2
EDIT: based on OP notes.
Netezza seems like IBM which means use the INSTR function, not CHARINDEX.
select
*,
min(instr(policynum, '/'), instr(policynum, '&')) as _sep1
from table2
https://www.ibm.com/support/knowledgecenter/en/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_2336.htm
FINDC & COUNTC functions are basically used for searching a character & counting them.
You can use LIKE operator from SQL to find characters with '%' and '_' wildcards
e.g. -
SELECT * FROM <table_name> WHERE <column_name> LIKE '%-%';
and
SELECT COUNT(*) FROM <table_name> WHERE <column_name> LIKE '%-%';
You can use regular expressions in the LIKE operator as well

Hive - SELECT inside WHEN clause of CASE function gives an error

I am trying to write a query in Hive with a Case statement in which the condition depends on one of the values in the current row (whether or not it is equal to its predecessor). I want to evaluate it on the fly, this way, therefore requiring a nested query, not by making it another column first and comparing 2 columns. (I was able to do the latter, but that's really second-best). Does anyone know how to make this work?
Thanks.
My query:
SELECT * ,
CASE
WHEN
(SELECT lag(field_with_duplicates,1) over (order by field_with_duplicates) FROM my_table b
WHERE b.id=a.id) = a.field_with_duplicates
THEN “Duplicate”
ELSE “”
END as Duplicate_Indicator
FROM my_table a
Error:
java.sql.SQLException: org.apache.spark.sql.AnalysisException: cannot recognize input near 'SELECT' 'lag' '(' in expression specification; line 4 pos 9
Notes:
The reason I needed the complicated 'lag' function is that the unique Id's in the table are not consecutive, but I don't think that's where it's at: I tested by substituting another simpler inner query and got the same error message.
Speaking of 'duplicates', I did search on this issue before posting, but the only SELECT's inside CASE's I found were in the THEN statement, and if that works the same, it suggests mine should work too.
You do not need the subquery inside CASE:
SELECT a.* ,
CASE
WHEN prev_field_with_duplicates = field_with_duplicates
THEN “Duplicate”
ELSE “”
END as Duplicate_Indicator
FROM (select a.*,
lag(field_with_duplicates,1) over (order by field_with_duplicates) as prev_field_with_duplicates
from my_table a
)a
or even you can use lag() inside CASE instead without subquery at all (I'm not sure if it will work in all Hive versions ):
CASE
WHEN lag(field_with_duplicates,1) over (order by field_with_duplicates) = field_with_duplicates
THEN “Duplicate”
ELSE “”
END as Duplicate_Indicator
Thanks to #MatBailie for the answer in his comment. Don't I feel silly...
Resolved

SQL : Coalesce within where clause giving error Oracle (Not in DB2)

I am trying to use COALESCE in WHERE clause, and I am getting the following error:
ORA-00907: missing right parenthesis Failed SQL stmt:
If I remove the COALESCE, I don't get the error anymore. I am not sure why would it give me this error as the parenthesis seem correct. Here's my SQL statement:
SELECT S.OPRID, A.OPRNAME, S.EMAIL_ADDR
FROM TABLE1 S, TABLE2 A
WHERE COALESCE(S.REHIRE_DT,S.ORIG_HIRE_DT)
BETWEEN (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM- DD'),'YYYY-MM-DD') - 3 DAY)
AND (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD') - 1 DAY)
AND S.EMPLSTATUS = 'A'
AND A.EMPLID = S.EMPLID
ORDER BY S.OPRID
Take the "DAY" word out. That is not used in oracle in that manner:
SELECT S.OPRID, A.OPRNAME, S.EMAIL_ADDR
FROM TABLE1 S, TABLE2 A
WHERE COALESCE(S.REHIRE_DT,S.ORIG_HIRE_DT)
BETWEEN (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM- DD'),'YYYY-MM-DD') - 3 )
AND (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD') - 1 )
AND S.EMPLSTATUS = 'A'
AND A.EMPLID = S.EMPLID
ORDER BY S.OPRID
"DAY" is a keyword to be used as part of the EXTRACT function - see Here
The default unit of subtraction from a date field is already in units of days. I am not familiar with DB2, but I am assuming that your usage of DAY is a DB2-specific attribute. That is probably not portable SQL. Yes, oracle's error messages can be confusing at times.
Now that I think about it, you can replace all that "TO_DATE" stuff with just:
BETWEEN TRUNC(SYSDATE)-3 AND TRUNC(SYSDATE)-1