WinSQL ORDER BY alphanumeric DB2 syntax - db2

I have the following set of data:
33
5A
5B
12
34A
2
34B
2B
11
10
12A
When I run the following SQL in WinSQL:
with input (f) as (
values ('33'), ('5A'), ('5B'),('12'), ('34A'),('2'), ('34B'), ('2B'), ('11'), ('10'), ('12A')
)
SELECT f
FROM input
ORDER BY f
I get the following result:
10
11
12
12A
2
2B
33
34A
34B
5A
5B
I would however want the result to be in this order:
2
2B
5A
5B
10
11
12
12A
33
34A
34B
I have tried the following:
with input (f) as (
values ('33'), ('5A'), ('5B'),('12'), ('34A'),('2'), ('34B'), ('2B'), ('11'), ('10'), ('12A')
)
SELECT
f
FROM input
ORDER BY CAST(CASE
WHEN f LIKE '[0-9]' THEN LEFT(CONCAT(0,f),1)
WHEN f LIKE '[0-9]%' THEN LEFT(CONCAT(0,f),1)
WHEN f LIKE '[0-9][0-9]%' THEN LEFT(f ,2)
ELSE NULL
END AS INT), f
But it doesn't work.
NOTE: This is for DB2 and all SQL-server functions (such as PATINDEX, SIGNED/UNSIGNED) are not available.

Try this:
ORDER BY CAST(replace(replace(replace(f,'A',''),'B',''),' ','') AS INT), f
(i.e. construct a sort field by getting rid of the non-numeric elements & converting to numeric, and then tie-break using the original value).

Related

Trying to partition to remove rows where two columns don't match sql

How can I filter out rows within a group that do not have matching values in two columns?
I have a table A like:
CODE
US_ID
US_PRICE
NON_US_ID
NON_US_PRICE
5109
57
10
75
10
0206
85
11
58
11
0206
85
15
33
14
0206
85
41
22
70
T100
20
10
49
NULL
T100
20
38
64
38
Within each CODE group, I want to check whether US_PRICE = NON_US_PRICE and remove that row from the resulting table.
I tried:
SELECT *,
CASE WHEN US_PRICE != NON_US_PRICE OVER (PARTITION BY CODE) END
FROM A;
but I think I am missing something when I try to partition by CODE.
I want the resulting table to look like
CODE
US_ID
US_PRICE
NON_US_ID
NON_US_PRICE
0206
85
15
33
14
0206
85
41
22
70
T100
20
10
49
NULL
For provided sample, simple WHERE clause could produce such result:
SELECT *
FROM A
WHERE US_PRICE IS DISTINCT FROM NON_US_PRICE;
IS DISTINCT FROM handles NULLs comparing to != operator.

How do I get old value and new values from audit table for all columns

I am using Spring boot, Spring JPA, and #auditable in order to maintain the audit logs in tables.
This is the duplicate question of - how do i get old value and new value from audit table.
Solution mentioned in the above question is working fo single column.
How we can get old and new values for the all columns ?
eg. current data
colm1 colm2 colm3 col4
f1 50 4/5/2017 3.38 33
f1 70 4/5/2017 3.40 33
f1 80 5/5/2017 3.40 44
f1 30 5/5/2017 5.40 55
Expected data
col_name colm1 oldvalue newvalue date
col2 f1 50 70 4/5/2017
col2 f1 70 80 5/5/2017
col4 f1 33 44 5/5/2017
col2 f1 80 30 5/5/2017
col4 f1 44 55 5/5/2017
first column should indicate the column name whose old and new value we are showing.
I need the old and new values of the all columns from 1st table.

How to select a column that doesnt exist and increments numerically to the final row

So this is a unique request.
Please understand I am limited to only making queries not creating new tables or new columns.
I have too create a query where i get all the classes within the school and give them a new identifier with a number made for simplicity e.g.
SchoolNumber
Classname
Simple Identifier
179535
4a
1
179535
4b
2
179535
5a
3
179535
5b
4
179535
6a
5
179535
6b
6
478953
1a
7
478953
2a
8
478953
3a
9
324598
1a
10
324598
1b
11
324598
1c
12
324598
2a
13
324598
2s
14
324598
2c
15
You get the Idea! How can I add a column with values incrementing without having to actually create a new column in the table since as I mentioned before my position does not allow me to create tables or columns or values
I came accross this on the internet
SELECT x1, x2, x1-x2 AS difference
FROM (VALUES
(2,42),
(13,7),
(42,2)
)
AS xoffsets(o1,o2)
CROSS JOIN LATERAL (
SELECT x+o1,x+o2 -- here we add the offsets above to x
FROM generate_series(1,3) AS t(x)
) AS t(x1, x2)
ORDER BY x1, x2;
This query proves one can generate a number sequence. My question is how in my case since I don't understand what is happening here?
my basic query looks something like this for reference
select distinct sch.schoolnumber, cl.classname, 'SI' as Simpleidentifier
from schools sch
join classschool cs on cs.schoolid = schools.id
join classes cl on cn.id = cs.classid
ROW_NUMBER() was specifically defined for a case like this one. It produces a simple number starting from 1.
For example:
select distinct
sch.schoolnumber,
cl.classname,
row_number() over(order by sch.schoolnumber, cl.classname) as Simpleidentifier
from schools sch
join classschool cs on cs.schoolid = schools.id
join classes cl on cn.id = cs.classid

Usage of DISTINCT in reversed int pairs duplicates elimination

I have a following question:
create table memorization_word_translation
(
id serial not null
from_word_id integer not null
to_word_id integer not null
);
This table stores pairs of integers, that are often in reverse order, for example:
35 36
35 37
36 35
37 35
37 39
39 37
Question is - if I make a query, for example:
select * from memorization_word_translation
where from_word_id = 35 or to_word_id = 35
I would get
35 36
35 37
36 35 - duplicate of 35 36
37 35 - duplicate of 35 37
How is to use DISTINCT in this example to filter out all duplicates even if they are reversed?
I want to keep it only like this:
35 36
35 37
You can do it with ROW_NUMBER() window function:
select from_word_id, to_word_id
from (
select *,
row_number() over (
partition by least(from_word_id, to_word_id),
greatest(from_word_id, to_word_id)
order by (from_word_id > to_word_id)::int
) rn
from memorization_word_translation
where 35 in (from_word_id, to_word_id)
) t
where rn = 1
See the demo.
demo:db<>fiddle
You could try a it with a small sorting algorithm (here a comparison) in combination with DISTINCT ON.
The DISTINCT ON clause works an arbitrary columns or terms, e.g. on a tuple. This CASE clause sorts the two columns into tuples and removes tied (ordered) ones. The source columns can be returned in your SELECT statement:
select distinct on (
CASE
WHEN (from_word_id >= to_word_id) THEN (from_word_id, to_word_id)
ELSE (to_word_id, from_word_id)
END
)
*
from memorization_word_translation
where from_word_id = 35 or to_word_id = 35

KDB selecting first row from each group

Very silly question... Consider the table t1 below which is sorted by sym.
t1:([]sym:(3#`A),(2#`B),(4#`C);val:10 40 12 50 58 75 22 103 108)
sym val
A 10
A 40
A 12
B 50
B 58
C 75
C 22
C 103
C 108
I want to select the first row corresponding to each sym, like this:
(`sym`val)!(`A`B`C;10j, 50j, 75j)
sym val
A 10
B 50
C 75
There's got to be a one-liner to do this. To get the LAST row for each sym, it would be as simple as select by sym from t1. Any hints?
select first val by sym from t1
Or for multiple columns, you can reverse the table and run your query:
select by sym from reverse t1
You could use fby
q)select from t1 where i=(first;i) fby sym
sym val
-------
A 10
B 50
C 75