Is using sequence in db2 statements possible? - sql

I am trying to execute following statement in DB2.
This works well.
SELECT NEXT VALUE FOR SCPYMNT.REM_QUERY_NO_SEQ
FROM sysibm.sysdummy1
However, this throws a database error.
SELECT (
CASE WHEN PYMT_SYS = 1 THEN NEXT VALUE FOR SCPYMNT.REM_QUERY_NO_SEQ
WHEN PYMT_SYS = 2 THEN 'dummy'
else 'dummy'
END )
FROM sysibm.sysdummy1
So Db2 gives the error below.
Category Timestamp Message
Statusbar 18.04.2016 11:47:39 DB2 Database Error: ERROR [428F9] [IBM][DB2] SQL0348N "NEXT VALUE FOR SCPYMNT.REM_QUERY_NO_SEQ" cannot be specified in this context. SQLSTATE=428F9
It seems to me there is not a syntax error.Does Db2 not let such queries that consists of case conditions and sequence?
#MichaelTiefenbacher,I put select examples as a demonstration.(What I am really trying to achieve is something like below.
SELECT NAME, QUERYNO
FROM FINAL TABLE (INSERT INTO EMPSAMP (NAME, SALARY, QUERYNO)
VALUES('Mary Smith', 35000.00,
CASE WHEN PYMT_SYS = 1 THEN NEXT VALUE FOR REM_SEQ
CASE WHEN PYMT_SYS = 2 NEXT VALUE FOR EFT_SEQ
));
I think question is more clearer now.

Sequences can be used to generate unique keys or numbers when inserting data into tables.
They are not used to generate unique numbers when selecting data.
For that you could either retrieve the field from the table where you used the sequence at insert time or you can use row_number() in the SELECT.
It also would be helpful to tell a little more what you want to achieve.

I found out that the answer is "No" according to IBM documentation.
NEXT VALUE expressions cannot be specified in the following contexts:
CASE expression
Here is the link

Insert from a union of selects:
SELECT NAME, QUERYNO
FROM FINAL TABLE
(
INSERT INTO EMPSAMP
SELECT
'Mary Smith', 35000.00, NEXT VALUE FOR REM_SEQ
FROM SYSIBM.SYSDUMMY1
WHERE PYMT_SYS = 1
UNION ALL
'Mary Smith', 35000.00, NEXT VALUE FOR EFT_SEQ
FROM SYSIBM.SYSDUMMY1
WHERE PYMT_SYS = 2
)

Related

Regex that matches strings with specific text not between text in BigQuery

I have the following strings:
step_1->step_2->step_3
step_1->step_3
step_1->step_2->step_1->step_3
step_1->step_2->step_1->step_2->step_3
What I would like to do is to capture the ones that between step_1 and step 3 there's no step_2.
The results should be like this:
string result
step_1->step_2->step_3 false
step_1->step_3 true
step_1->step_2->step_1->step_3 true
step_1->step_2->step_1->step_2->step_3 false
I have tried to use the negative lookahead but I found out that BigQuery doesn't support it. Any ideas?
You are essentially looking for when the pattern does not exist. The following regex would support that embedded in a case statement. This would not support a scenario where you have both conditions in a single string, however that was not a scenario you listed in your sample data.
Try the following:
with sample_data as (
select 'step_1->step_2->step_3' as string union all
select 'step_1->step_3' union all
select 'step_1->step_2->step_1->step_3' union all
select 'step_1->step_2->step_1->step_2->step_3' union all
select 'step_1->step_2->step_1->step_2->step_2->step_3' union all
select 'step_1->step_2->step_1->step_2->step_2'
)
select
string,
-- CASE WHEN regexp_extract(string, r'step_1->(\w+)->step_3') IS NULL THEN TRUE
CASE WHEN regexp_extract(string, r'1(->step_2)+->step_3') IS NULL THEN TRUE
ELSE FALSE END as result
from sample_data
This results in:
Consider also below option
select string,
not regexp_contains(string, r'step_1->(step_2->)+step_3\b') as result
from your_table
I believe #Daniel_Zagales answer is the one you were expecting. However here is a broader solution that can maybe be interesting in your usecase:it consists in using arrays
WITH sample AS (
SELECT 'step_1->step_2->step_3' AS path
UNION ALL SELECT 'step_1->step_3'
UNION ALL SELECT 'step_1->step_2->step_1->step_3'
UNION ALL SELECT 'step_1->step_2->step_1->step_2->step_3'
),
temp AS (
SELECT
path,
SPLIT(REGEXP_REPLACE(path,'step_', ''), '->') AS sequences
FROM
sample)
SELECT
path,
position,
flattened AS current_step,
LAG(flattened) OVER (PARTITION BY path ORDER BY OFFSET ) AS previous_step,
LEAD(flattened) OVER (PARTITION BY path ORDER BY OFFSET ) AS following_step
FROM
temp,
temp.sequences AS flattened
WITH
OFFSET AS position
This query returns the following table
The concept is to get an array of the step number (splitting on '->' and erasing 'step_') and to keep the OFFSET (crucial as UNNESTing arrays does not guarantee keeping the order of an array).
The table obtained contains for each path and step of said path, the previous and following step. It is therefore easy to test for instance if successive steps have a difference of 1.
(SELECT * FROM <previous> WHERE ABS(current_step-previous_step) != 1 for example)
(CASTing to INT required)

Oracle (SQL Statements) - Using CASE with WHERE CLAUSE

Dear Experts,
I preparing an SQL report to display the data with Format_Check validations using CASE. I have provided the example,issues and expectation below:
Table Structure:enter image description here
SQL Statement:
SELECT
ID,PRODUCT,COMMENTS
CASE WHEN SUBSTR(COMMENTS,1,35)=REGEXP_SUBSTR (COMMENTS,'(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)',1,1)
AND
LENGTH(TRIM(REGEXP_SUBSTR (COMMENTS, '(\S*)(\s)', 1, 2)))=8
AND
REGEXP_LIKE(TRIM(REGEXP_SUBSTR (COMMENTS, '(\S*)(\s)', 1, 1)),'(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)')
THEN 'Correct Format'
ELSE 'Incorrect_Format'
END AS Format_Check
FROM TEST_TABLE
SQL Output:
enter image description here
SQL Output Explanation:
Checks whether COMMENTS column is 35 Character long, also checks the format numbers and spaces. SUBSTR(COMMENTS,1,35)=REGEXP_SUBSTR
(COMMENTS,'(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)',1,1)
Checks whether the comments after first space is 8 characters long LENGTH(TRIM(REGEXP_SUBSTR (COMMENTS, '(\S*)(\s)', 1, 2)))=8
Checks the first 8 characters is digit/number. REGEXP_LIKE(TRIM(REGEXP_SUBSTR (COMMENTS, '(\S*)(\s)', 1,
1)),'(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)')
Expectation:
I need only the 'Incorrect Format' comments to be displayed when the SQL is executed, I don't wish to see the 'Correct Format' comments. However I need your advise on whether this case be used with WHERE clause to display only incorrect format COMMENTS alone.
I referred previous queries related to WHERE and CASE, however I can't figure out on how pass my case in WHERE clause.
Thanks for your help.
If you want to display the incorrect format columns, you can wrap your query with another one:
SELECT id, product, comment, format_check
FROM (
SELECT id, product, comment, CASE WHEN .... END AS format_check
FROM test_table
)
WHERE format_check = 'Incorrect_Format';
BTW, your question is easier to answer if you show your table and data with SQL instead of an image, for instance like:
CREATE TABLE test_table (id NUMBER, product VARCHAR2(10), comments VARCHAR2(50));
INSERT INTO test_table VALUES (1,'Laptop', '00000001 01012020 02022020 03032020');
INSERT INTO test_table VALUES (1,'PC', ' 00000001 01012020 02022020 0034');
Furthermore, I believe the regular expression can be simplified. Please provide a bit more detail if you're interested...
If you do not wish to see the correct format in the result at all then you can omit the calculation of the format in select clause. Rather use it in Where clause as follows:
SELECT ID,
PRODUCT,
COMMENTS,
'Incorrect_Format' AS format_check
FROM TEST_TABLE
WHERE CASE WHEN SUBSTR(COMMENTS,1,35)=REGEXP_SUBSTR (COMMENTS,'(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\s)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)',1,1)
AND
LENGTH(TRIM(REGEXP_SUBSTR (COMMENTS, '(\S*)(\s)', 1, 2)))=8
AND
REGEXP_LIKE(TRIM(REGEXP_SUBSTR (COMMENTS, '(\S*)(\s)', 1, 1)),'(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)')
THEN 'Correct Format'
ELSE 'Incorrect_Format'
END AS = 'Incorrect_Format'

Read multiple columns from single table based on our input string

I want to select multiple columns from single table based on my given input string in sql select statement.
Example :
If input="table_medical" i want to select the columns like medi_col1,medi_col2,medi_col2
If input="table_pharmacy" i want to select the columns like medi_phar1,medi_phar2,medi_phar1
sql("select
case when $input="table_medical" then medi_col1) //like this
please help me to complete this.
If you want this in a single query, then the same number of columns is needed -- and have compatible types.
One method uses union all:
select medi_col1, medi_col2, medi_col2
from t
where #input = 'table_medical'
union all
select medi_phar1, medi_phar2, medi_phar1
from t
where #input = 'table_pharmacy';
SET #input="table_medical";
SELECT
CASE WHEN #input="table_medical" THEN medi_col1 ELSE medi_phar1 END as medi_col1,
CASE WHEN #input="table_medical" THEN medi_col2 ELSE medi_phar2 END as medi_col2
CASE WHEN #input="table_medical" THEN medi_col3 ELSE medi_phar3 END as col3
FROM MyTable
Data types for medi_col1 and medi_phar1 needs to be same (and for the rest of columns too)

How to display the whole number only if it starts with two characters otherwise leave it blank. SQL query

I need to display the whole number in a field if it starts with "AB" otherwise do not show/display the number.
Your question is missing code of how you display this (since you wrote you need to display it to the field) so i can't answer you with actual code but here is solution.
If you want to select only rows which column1 starts with AB then use LIKE function. So condition at selecting command is Select * from yourtable where column1 LIKE 'AB%'
If you already selected and displayed data, let's say in datagridview, and you want to fill textbox with string that contains AB then you would go through all rows at specific column and look for it with string.Contains("AB");
So basically you put this command in foreach loop and you have it.
I was wrong. You can use a LIKE, just not in the WHERE clause.
;WITH testdata AS (
SELECT 'aw12354' AS val UNION ALL
SELECT 'a12b344' UNION ALL
SELECT 'AB11111' UNION ALL
SELECT '11AB111' UNION ALL
SELECT '11111AB' UNION ALL
SELECT 'ab22222'
)
SELECT
CASE WHEN val LIKE 'AB%' THEN val ELSE NULL END AS valFull
, CASE WHEN val LIKE 'AB%' THEN SUBSTRING(val,3,len(val)) ELSE NULL END AS valNums
FROM testdata
;
You can also use CLR to build a regex solution, but that is a LOT more involved.

SSMS - every SELECT statement creates extra empty line - how to suppress?

If I set in SQL Management Studio to produce an output to Text (not to grid or to file) and run following:
SET NOCOUNT ON
SELECT '1'
SELECT '2'
SELECT '1'
I get this:
1
2
1
How to remove extra new line after every line?
I set as default in Tools->Options following:
1. Output format as TAB delimited
2. Excluded column headers in the result set
3. Created a New Query
UPDATE:
Previous query is shown for sake of simplicity. Please take this one as a question:
SELECT 1+2
SELECT 'A FOX'
SELECT 1,2,3
Want to see no extra line between lines, e.g:
3
A FOX
1 2 3
You are getting three separate result sets - one for each select.
In order to get a single result set (with duplicates) you need to UNION ALL the selects:
SET NOCOUNT ON
SELECT '1' UNION ALL
SELECT '2' UNION ALL
SELECT '1'
See UNION (Transact-SQL) on MSDN for details.
Update:
What you want to do is not possible. The types and numbers of the fields are different in each select - you can't UNION them.
You can't have a single result set that has different number of columns per row or with different data types per row.
Well, instead of posting comment, I decided to post answer, since it may help someone.
The output of the stored procedure I need to paste in Excel and apply "copy format" from template.
I resolved this problem this way:
Initial statement I have
SELECT 'Report Header'
SELECT ''
SELECT 'Line of report',1
SELECT 'Line of report',23
SELECT * FROM SUBREPORT
SELECT 'SUBTOTAL:',(select count(*) from another_table)
SELECT ''
SELECT 'REPORT GENERATED AT ', GetDate()
I updated to this:
SELECT 'Report Header'
SELECT '[NEWLINE]'
SELECT 'Line of report',1
SELECT 'Line of report',23
SELECT * FROM SUBREPORT
SELECT 'SUBTOTAL:',(select count(*) from another_table)
SELECT '[NEWLINE]'
SELECT 'REPORT GENERATED AT ', GetDate()
Since extra empty lines breaks formatting, I have to remove them.
I took the text output and pasted in Word.
Replaced "^p^p" with "^p", and then "[NEWLINE]" with "" (nothing).
Copy-Paste to Excel and copy format from template.
Done.
I would appreciate if someone can suggest more elegant solution.