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

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)

Related

Using a PostgreSQL function inside a loop

Suppose I have a PostgreSQL function that takes 2 parameters: id (INT), email (TEXT) and can be called like this:
SELECT * FROM my_function(101, 'myemail#gmail.com')
I want to run a SELECT query from a table that would return multiple id's:
SELECT id FROM mytable
| id |
--+------+
| 101 |
--+------+
| 102 |
--+------+
| 103 |
How would I loop through and plug each of the returned id's into my function in a query. FOr this example just assume the default email is alwasy "myemail#gmail.com"
I'm on mobile so I can't test it, but I think maybe this will work.
SELECT * FROM (select my_function(id, 'myemail#gmail.com') from mytable);
You can use a cross join:
SELECT *
FROM my_table mt
cross join lateral my_function(mt.id, 'myemail#gmail.com') as mf

is there something similar to column_id in 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

Why am I getting a false average when applied on temporary table column

I'm trying to get the average of words based on each message.body count of words from messages table
an example of that would be
**message.body**
-------------------
-->"aaz aae aar"
-->"aaz"
-->"aaz aae"
Output must be: AVG( 3 + 1 + 2 ) = 2
For that I've been applying the following query
SELECT AVG(temp.words) FROM (SELECT (array_length(string_to_array(messages.body,' '),1)) AS words FROM messages) AS temp
message.body is just text.
Any help will be appreciated.
giving the result you expect:
t=# with messages(body) as (values('aaz aae aar'),('aaz'),('aaz aae')) SELECT AVG(temp.words) FROM (SELECT (array_length(string_to_array(messages.body,' '),1)) AS words FROM messages) AS temp;
avg
--------------------
2.0000000000000000
(1 row)
t=# with messages(body) as (values('aaz aae aar'),('aaz'),('aaz aae')) SELECT *FROM (SELECT (array_length(string_to_array(messages.body,' '),1)) AS words,messages.body FROM messages) AS temp;
words | body
-------+-------------
3 | aaz aae aar
1 | aaz
2 | aaz aae
(3 rows)
I'm answering my question:
it happens that average function in postgres only accepts Floats as an argument, for that someone needs to cast the input before. Like this:
SELECT(AVG (temporary_.words)) AS average_amount FROM (SELECT CAST(array_length(string_to_array(messages.body,' '),1) AS FLOAT) AS words FROM messages WHERE body!='' ) AS temporary_

postgres offset by value not number

I have a table with at least a "name" column and an "ordinal_position" column. I wish to loop each row starting from a certain row the user inputs. Let's say the user inputs "John", and that his ordinal_position is 6 (out of a 10 total). How do I loop only the last 4 rows without using a subquery? I've tried using the "OVER()" window function but it doesn't seem to work on the offset part of the query, and that same offset only takes numbers (as far as I know) not strings.
EDIT (in response to klin):
INSERT INTO foo(id,name,ordinal_position) VALUES
(DEFAULT,'Peter',1),
(DEFAULT,'James',2),
(DEFAULT,'Freddy',3),
(DEFAULT,'Mark',4),
(DEFAULT,'Jack',5),
(DEFAULT,'John',6),
(DEFAULT,'Will',7),
(DEFAULT,'Robert',8),
(DEFAULT,'Dave',9),
(DEFAULT,'Michael',10);
so in my FOR, since the user inputed "John" I want to loop through Will-Michael. Something like the following but without a subquery:
SELECT * FROM foo ORDER BY ordinal_position OFFSET
(SELECT ordinal_position FROM foo WHERE name='John');
Unfortunately, you have to query the table to find an ordinal_position for a given name.
However, do not use offset. You can do it in where clause, for large tables it will be much faster:
select *
from foo
where ordinal_position > (select ordinal_position from foo where name = 'John')
order by ordinal_position;
id | name | ordinal_position
----+---------+------------------
7 | Will | 7
8 | Robert | 8
9 | Dave | 9
10 | Michael | 10
(4 rows)

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