is there something similar to column_id in postgresql? - postgresql

Just as in oracle database we have column_id in all_tabs_columns is there a similar field for postgresql?
For example if in oracle we can order by column id by selecting from columns do we have a similar query in pgsql ?

The column attnum in pg_attribute shows the order of a column in a table.

yes, you can also order by column number in Postgres:
with sampledata(a,b) as (values (1,'z'),(2,'y'),(3,'x'))
SELECT a,b
FROM sampledata
ORDER BY 1;
a | b
---+---
1 | z
2 | y
3 | x
(3 rows)
with sampledata(a,b) as (values (1,'z'),(2,'y'),(3,'x'))
SELECT a,b
FROM sampledata
ORDER BY 2;
a | b
---+---
3 | x
2 | y
1 | z
(3 rows)

The closest equivalent to all_tab_columns is information_schema.columns
So you are probably looking for something along the lines:
select column_name
from information_schema.columns
where table_name = '...'
order by ordinal_position;

In postgresql. Let's say you have a table with the name Table with the following columns:
Col 1,
Col 2,
Col 3
You can completely reorder the columns in postgresql by writing the query
SELECT
Col 3,
Col 2,
Col 1
FROM
Table

Related

DB2 - Concat all values in a column into a Single string

Let's say I have a table like this:
test
Col1
Col2
A
1
B
1
C
1
D
2
I am doing query select col1 from test where col2 = 1;
This will return a column with values A B and C in 3 separate rows.
I want the SQL to return a single row with value A|B|C. Is this possible to do? If it is how should I do it?
you can use LISTAGG function like this:
SELECT LISTAGG(col1, ',')
If LISTAGG is not available, it can be reproduced with XMLAGG:
SELECT SUBSTR(XMLSERIALIZE(XMLAGG(XMLTEXT('|'||"Col1"))),2)
FROM "test"
WHERE "Col2" = 1

PSQL filter each group of rows

Recently I've faced with pretty rare filtering case in PSQL.
My question is: How to filter redundant elements in each group of the grouped table?
For example: we have a nexp table:
id | group_idx | filter_idx
1 1 x
2 3 z
3 3 x
4 2 x
5 1 x
6 3 x
7 2 x
8 1 z
9 2 z
Firstly, to group rows:
SELECT group_idx FROM table
GROUP BY group_idx;
But how I can filter redundant fields (filter_idx = z) from each group after grouping?
P.S. I can't just write like that because I need to find groups firstly.
SELECT group_idx FROM table
where filter_idx <> z;
Thanks.
Assuming that you want to see all groups at all times, even when you filter out all records of some group:
drop table if exists test cascade;
create table test (id integer, group_idx integer, filter_idx character);
insert into test
(id,group_idx,filter_idx)
values
(1,1,'x'),
(2,3,'z'),
(3,3,'x'),
(4,2,'x'),
(5,1,'x'),
(6,3,'x'),
(7,2,'x'),
(8,1,'z'),
(9,2,'z'),
(0,4,'y');--added an example of a group that would be discarded using WHERE.
Get groups in one query, filter your rows in another, then left join the two.
select groups.group_idx,
string_agg(filtered_rows.filter_idx,',')
from
(select distinct group_idx from test) groups
left join
(select group_idx,filter_idx from test where filter_idx<>'y') filtered_rows
using (group_idx)
group by 1;
-- group_idx | string_agg
-------------+------------
-- 3 | z,x,x
-- 4 |
-- 2 | x,x,z
-- 1 | x,x,z
--(4 rows)

Postgres, how to access all the tables in a database iteratively, subquery?

Hi Postgres community :D
I am trying to read contents of tables to grasp the picture of them.
So, my question is:
How could it be done to display all the head of tables inside a database giving same result as below naive tidious queries.
I guess there must be a fancy way of just one line query to do this..
Please help me out!
# naive
SELECT * FROM mytable0001;
SELECT * FROM mytable0002;
SELECT * FROM mytable0003;
...
SELECT * FROM mytable9999;
# wannabe
SELECT * FROM foo (SELECT table_name FROM information_schema.tables) AS foo limit 5;
Thank you in advance!
You can try to use psql CLI and \gexec command.
With following input:
select format('select * from %s;',tablename)
from pg_tables
where tablename like 'table%'
\gexec
You get in one go:
select format('select * from %s;',tablename)
from pg_tables
where tablename like 'table%'
select * from table0001;
c1 | c2
----+---------
1 | table 1
(1 row)
select * from table0002;
c1 | c2
----+---------
1 | table 2
2 | table 2
(2 rows)
select * from table0003;
c1 | c2
----+---------
1 | table 3
2 | table 3
3 | table 3
(3 rows)

SQL to remove rows with duplicated value while keeping one

Say I have this table
id | data | value
-----------------
1 | a | A
2 | a | A
3 | a | A
4 | a | B
5 | b | C
6 | c | A
7 | c | C
8 | c | C
I want to remove those rows with duplicated value for each data while keeping the one with the min id, e.g. the result will be
id | data | value
-----------------
1 | a | A
4 | a | B
5 | b | C
6 | c | A
7 | c | C
I know a way to do it is to do a union like:
SELECT 1 [id], 'a' [data], 'A' [value] INTO #test UNION SELECT 2, 'a', 'A'
UNION SELECT 3, 'a', 'A' UNION SELECT 4, 'a', 'B'
UNION SELECT 5, 'b', 'C' UNION SELECT 6, 'c', 'A'
UNION SELECT 7, 'c', 'C' UNION SELECT 8, 'c', 'C'
SELECT * FROM #test WHERE id NOT IN (
SELECT MIN(id) FROM #test
GROUP BY [data], [value]
HAVING COUNT(1) > 1
UNION
SELECT MIN(id) FROM #test
GROUP BY [data], [value]
HAVING COUNT(1) <= 1
)
but this solution has to repeat the same group by twice (consider the real case is a massive group by with > 20 columns)
I would prefer a simpler answer with less code as oppose to complex ones. Is there any more concise way to code this?
Thank you
You can use one of the methods below:
Using WITH CTE:
WITH CTE AS
(SELECT *,RN=ROW_NUMBER() OVER(PARTITION BY data,value ORDER BY id)
FROM TableName)
DELETE FROM CTE WHERE RN>1
Explanation:
This query will select the contents of the table along with a row number RN. And then delete the records with RN >1 (which would be the duplicates).
This Fiddle shows the records which are going to be deleted using this method.
Using NOT IN:
DELETE FROM TableName
WHERE id NOT IN
(SELECT MIN(id) as id
FROM TableName
GROUP BY data,value)
Explanation:
With the given example, inner query will return ids (1,6,4,5,7). The outer query will delete records from table whose id NOT IN (1,6,4,5,7).
This fiddle shows the records which are going to be deleted using this method.
Suggestion: Use the first method since it is faster than the latter. Also, it manages to keep only one record if id field is also duplicated for the same data and value.
I want to add MYSQL solution for this query
Suggestion 1 : MySQL prior to version 8.0 doesn't support the WITH clause
Suggestion 2 : throw this error (you can't specify table TableName for update in FROM clause
So the solution will be
DELETE FROM TableName WHERE id NOT IN
(SELECT MIN(id) as id
FROM (select * from TableName) as t1
GROUP BY data,value) as t2;

mySQL query: How to insert with UNION?

I am kind of new to mySQL:s union functions, at least when doing inserts with them. I have gotten the following to work based upon a example found on the net:
INSERT INTO tableOne(a, b)
SELECT a, $var FROM tableOne
WHERE b = $var2
UNION ALL SELECT $var,$var
Ok, nothing strange about that. But what happens when I want to insert a third value into the database that has nothing to do with the logic of the Select being done?
Like : INSERT INTO tableOne(a, b, c )
How could that be done?
You can "select" literal values too:
mysql> select 'hello', 1;
+-------+---+
| hello | 1 |
+-------+---+
| hello | 1 |
+-------+---+
1 row in set (0.00 sec)
Hence, you can also use that in INSERT INTO ... SELECT FROM and UNIONs.
INSERT INTO someTable (a, b, c) VALUES
SELECT id, name, 5
FROM someOtherTable
UNION
SELECT id, alias, 8
FROM anotherTable