Can't remove trailing spaces - db2

I'm trying to remove trailing spaces without success:
select trim(trailing ' ' from '1234 '), '56' from sysibm.sysdummy1;
1 2
--------------------------- --
1234 56
What am I missing?

It is documented that trim will leave the data type as is - check out the Knowledge Center
describe "select trim( '1234 '), '56' from sysibm.sysdummy1"
Column Information
Number of columns: 2
SQL type Type length Column name Name length
-------------------- ----------- ------------------------------ -----------
448 VARCHAR 27 1 1
448 VARCHAR 2 2 1
If you want to change the look / data type of the result you can cast it to the length or data type you need
select varchar(trim( '1234 '), 5), '56' from sysibm.sysdummy1"
1 2
----- --
1234 56
1 record(s) selected.

Do you mean:
select trim(trailing ' ' from '1234 ')|| '56' from sysibm.sysdummy1
Specifically:
select length(trim(trailing ' ' from '1234 ')|| '56') from sysibm.sysdummy1;
1
-----------
6
1 record(s) selected
.

Other method, if your db2 version enable RPAD function (V7R2 on iserie) :
select rpad('1234 ', 5, ' '), '56'
from sysibm.sysdummy1

Related

How to get the result of table contains numeric and strings using where condition in postgres

I have a table like below
When I select item_no>'1623G' from above table
I want to print the result below
1623H | 1623I | 1666 | 1674 | 1912 | 1952 | 1953
I am trying below command
select * from t where substring(item_no,'([0-9]+)') :: int > 1623G
But it's not giving result
please help
I would go the regexp way:
demo:db<>fiddle
WITH cte AS (
SELECT
item_no,
regexp_replace(item_no, '\D', '', 'g')::int AS digit,
regexp_replace(item_no, '\d', '', 'g') AS nondigit,
regexp_replace('200a', '\D', '', 'g')::int AS compare_digit,
regexp_replace('200a', '\d', '', 'g') AS compare_nondigit
FROM t
)
SELECT
item_no
FROM
cte
WHERE
(digit > compare_digit) OR (digit = compare_digit AND nondigit > compare_nondigit)
Splitting both values (the row value and the comparing one) into its both parts (digits and non-digits) and compare each part separately.
I am curious if there is better solution.
You can use CONVERT_TO as:
testdb1=# CREATE TABLE t (item_no varchar(20));
CREATE TABLE
testdb1=# INSERT INTO t VALUES('2'),('20'),('200'),('200a'),('200b'),('200c'),('2000');
INSERT 0 7
testdb1=# SELECT * FROM t;
item_no
---------
2
20
200
200a
200b
200c
2000
(7 rows)
testdb1=# select * from t where substring(convert_to(item_no,'SQL_ASCII')::text,3)::int > substring(convert_to('2a','SQL_ASCII')::text,3)::int;
item_no
---------
200
200a
200b
200c
2000
(5 rows)
testdb1=# select * from t where substring(convert_to(item_no,'SQL_ASCII')::text,3)::int > substring(convert_to('150','SQL_ASCII')::text,3)::int;
item_no
---------
200
200a
200b
200c
2000
(5 rows)

PostgreSQL - dynamic INSERT on column names

I'm looking to dynamically insert a set of columns from one table to another in PostgreSQL. What I think I'd like to do is read in a 'checklist' of column headings (those columns which exist in table 1 - the storage table), and if they exist in the export table (table 2) then insert them in all at once from table 1. Table 2 will be variable in its columns though - once imported ill drop it and import new data to be imported with potentially different column structure. So I need to import it based on the column names.
e.g.
Table 1. - The storage table
ID NAME YEAR LITH_AGE PROV_AGE SIO2 TIO2 CAO MGO COMMENTS
1 John 1998 2000 3000 65 10 5 5 comment1
2 Mark 2005 2444 3444 63 8 2 3 comment2
3 Luke 2001 1000 1500 77 10 2 2 comment3
Table 2. - The export table
ID NAME MG# METHOD SIO2 TIO2 CAO MGO
1 Amy 4 Method1 65 10 5 5
2 Poe 3 Method2 63 8 2 3
3 Ben 2 Method3 77 10 2 2
As you can see the export table may include columns which do not exist in the storage table, so these would be ignored.
I want to insert all of these columns at once, as I've found if I do it individually by column it extends the number of rows each time on the insert (maybe someone can solve this issue instead? Currently I've written a function to check if a column name exists in table 2, if it does, insert it, but as said this extends the rows of the table every time and NULL the rest of the columns).
The INSERT line from my function:
EXECUTE format('INSERT INTO %s (%s) (SELECT %s::%s FROM %s);',_tbl_import, _col,_col,_type,_tbl_export);
As a type of 'code example' for my question:
EXECUTE FORMAT('INSERT INTO table1 (%s) (SELECT (%s) FROM table2)',columns)
where 'columns' would be some variable denoting the columns that exist in the export table that need to go into the storage table. This will be variable as table 2 will be different every time.
This would ideally update Table 1 as:
ID NAME YEAR LITH_AGE PROV_AGE SIO2 TIO2 CAO MGO COMMENTS
1 John 1998 2000 3000 65 10 5 5 comment1
2 Mark 2005 2444 3444 63 8 2 3 comment2
3 Luke 2001 1000 1500 77 10 2 2 comment3
4 Amy NULL NULL NULL 65 10 5 5 NULL
5 Poe NULL NULL NULL 63 8 2 3 NULL
6 Ben NULL NULL NULL 77 10 2 2 NULL
UPDATED answer
As my original answer did not meet requirement came out later but was asked to post an alternative example for information_schema solution so here it is.
I made two versions for solutions:
V1 - is equivalent to already given example using information_schema. But that solution relies on table1 column DEFAULTs. Meaning, if table1 column that does not exist at table2 does not have DEFAULT NULL then it will be filled with whatever the default is.
V2 - is modified to force 'NULL' in case of two table columns mismatch and does not inherit table1 own DEFAULTs
Version1:
CREATE OR REPLACE FUNCTION insert_into_table1_v1()
RETURNS void AS $main$
DECLARE
columns text;
BEGIN
SELECT string_agg(c1.attname, ',')
INTO columns
FROM pg_attribute c1
JOIN pg_attribute c2
ON c1.attrelid = 'public.table1'::regclass
AND c2.attrelid = 'public.table2'::regclass
AND c1.attnum > 0
AND c2.attnum > 0
AND NOT c1.attisdropped
AND NOT c2.attisdropped
AND c1.attname = c2.attname
AND c1.attname <> 'id';
-- Following is the actual result of query above, based on given data examples:
-- -[ RECORD 1 ]----------------------
-- string_agg | name,si02,ti02,cao,mgo
EXECUTE format(
' INSERT INTO table1 ( %1$s )
SELECT %1$s
FROM table2
',
columns
);
END;
$main$ LANGUAGE plpgsql;
Version2:
CREATE OR REPLACE FUNCTION insert_into_table1_v2()
RETURNS void AS $main$
DECLARE
t1_cols text;
t2_cols text;
BEGIN
SELECT string_agg( c1.attname, ',' ),
string_agg( COALESCE( c2.attname, 'NULL' ), ',' )
INTO t1_cols,
t2_cols
FROM pg_attribute c1
LEFT JOIN pg_attribute c2
ON c2.attrelid = 'public.table2'::regclass
AND c2.attnum > 0
AND NOT c2.attisdropped
AND c1.attname = c2.attname
WHERE c1.attrelid = 'public.table1'::regclass
AND c1.attnum > 0
AND NOT c1.attisdropped
AND c1.attname <> 'id';
-- Following is the actual result of query above, based on given data examples:
-- t1_cols | t2_cols
-- --------------------------------------------------------+--------------------------------------------
-- name,year,lith_age,prov_age,si02,ti02,cao,mgo,comments | name,NULL,NULL,NULL,si02,ti02,cao,mgo,NULL
-- (1 row)
EXECUTE format(
' INSERT INTO table1 ( %s )
SELECT %s
FROM table2
',
t1_cols,
t2_cols
);
END;
$main$ LANGUAGE plpgsql;
Also link to documentation about pg_attribute table columns if something is unclear: https://www.postgresql.org/docs/current/static/catalog-pg-attribute.html
Hopefully this helps :)

How to compute the sum of multiple columns in PostgreSQL

I would like to know if there's a way to compute the sum of multiple columns in PostgreSQL.
I have a table with more than 80 columns and I have to write a query that adds each value from each column.
I tried with SUM(col1, col2, col3 etc) but it didn't work.
SELECT COALESCE(col1,0) + COALESCE(col2,0)
FROM yourtable
It depends on how you'd like to sum the values. If I read your question correctly, you are looking for the second SELECT from this example:
template1=# SELECT * FROM yourtable ;
a | b
---+---
1 | 2
4 | 5
(2 rows)
template1=# SELECT a + b FROM yourtable ;
?column?
----------
3
9
(2 rows)
template1=# SELECT SUM( a ), SUM( b ) FROM yourtable ;
sum | sum
-----+-----
5 | 7
(1 row)
template1=# SELECT SUM( a + b ) FROM yourtable ;
sum
-----
12
(1 row)
template1=#
Combined the current answers and used this to get total SUM:
SELECT SUM(COALESCE(col1,0) + COALESCE(col2,0)) FROM yourtable;
SELECT(
SELECT SUM(t.f)
FROM (VALUES (yourtable.col1), (yourtable.col2), (yourtable.col3)) t(f)
)
FROM yourtable;

SQL Query Question

I am using the following query to list these records between specified dates.But ,it's not working.Also,don't gives me error.Just is coming blank screen.it's has column name.
Any problem the following query?
SET DATEFORMAT dmy
select *from tamirarizakaydi where tarih between '31.01.2011 ' and ' 04.02.2011'
thanks in advance.
The leading and trailing spaces don't make any difference as far as I can see.
SET DATEFORMAT dmy
select CAST('31.01.2011 ' as date) , CAST(' 04.02.2011' as date), CAST('31.01.2011 ' as datetime), CAST(' 04.02.2011' as datetime)
Returns
---------- ---------- ----------------------- -----------------------
2011-01-31 2011-02-04 2011-01-31 00:00:00.000 2011-02-04 00:00:00.000
I'm going to guess that tarih is stored as a string or you don't have any matching rows.
If tarih is a character based column then your query will be doing a lexicographic comparison and look for rows where tarih >= '31.01.2011 ' and 'tarih <= ' 04.02.2011' No rows can match this condition as the end of the range is alphabetically before the start of the range.

Convert Varchar to Ascii

I'm trying to convert the contents of a VARCHAR field to be unique number that can be easily referenced by a 3rd party.
How can I convert a varchar to the ascii string equivalent? In TSQL? The ASCII() function converts a single character but what can I do to convert an entire string?
I've tried using
CAST(ISNULL(ASCII(Substring(RTRIM(LTRIM(PrimaryContactRegion)),1,1)),'')AS VARCHAR(3))
+ CAST(ISNULL(ASCII(Substring(RTRIM(LTRIM(PrimaryContactRegion)),2,1)),'')AS VARCHAR(3))
....but this is tedious, stupid looking, and just doesn't really work if I had long strings. Or if it is better how would I do the same thing in SSRS?
try something like this:
DECLARE #YourString varchar(500)
SELECT #YourString='Hello World!'
;WITH AllNumbers AS
(
SELECT 1 AS Number
UNION ALL
SELECT Number+1
FROM AllNumbers
WHERE Number<LEN(#YourString)
)
SELECT
(SELECT
ASCII(SUBSTRING(#YourString,Number,1))
FROM AllNumbers
ORDER BY Number
FOR XML PATH(''), TYPE
).value('.','varchar(max)') AS NewValue
--OPTION (MAXRECURSION 500) --<<needed if you have a string longer than 100
OUTPUT:
NewValue
---------------------------------------
72101108108111328711111410810033
(1 row(s) affected)
just to test it out:
;WITH AllNumbers AS
(
SELECT 1 AS Number
UNION ALL
SELECT Number+1
FROM AllNumbers
WHERE Number<LEN(#YourString)
)
SELECT SUBSTRING(#YourString,Number,1),ASCII(SUBSTRING(#YourString,Number,1)),* FROM AllNumbers
OUTPUT:
Number
---- ----------- -----------
H 72 1
e 101 2
l 108 3
l 108 4
o 111 5
32 6
W 87 7
o 111 8
r 114 9
l 108 10
d 100 11
! 33 12
(12 row(s) affected)
Also, you might want to use this:
RIGHT('000'+CONVERT(varchar(max),ASCII(SUBSTRING(#YourString,Number,1))),3)
to force all ASCII values into 3 digits, I'm not sure if this is necessary based on your usage or not.
Output using 3 digits per character:
NewValue
-------------------------------------
072101108108111032087111114108100033
(1 row(s) affected)
Well, I think that a solution to this will be very slow, but i guess that you could do something like this:
DECLARE #count INT, #string VARCHAR(100), #ascii VARCHAR(MAX)
SET #count = 1
SET #string = 'put your string here'
SET #ascii = ''
WHILE #count <= DATALENGTH(#string)
BEGIN
SELECT #ascii = #ascii + '&#' + ASCII(SUBSTRING(#string, #count, 1)) + ';'
SET #count = #count + 1
END
SET #ascii = LEFT(#ascii,LEN(#ascii)-1)
SELECT #ascii
I'm not in a pc with a database engine, so i can't really test this code. If it works, then you can create a UDF based on this.