If we can make the assumption that the unnest()
operation will always return a set where a member "id" is listed followed by its role in a single column of text
entries, then I've written up a quick solution for you.
I made a quick data set as:
CREATE TABLE mylist (entry text);
INSERT INTO mylist VALUES
('n240045827'),
('admin_centre'),
('w185481610'),
('outer'),
('w191987461'),
('outer'),
('w166286278'),
('outer'),
('w166290573'),
('outer'),
('w65481875'),
('outer'),
('w166278211'),
('outer'),
('w166278224'),
('outer'),
('w166278225'),
('outer'),
('w166278227'),
('outer'),
('w185148605'),
('outer');
Assuming we can return this, then the script
WITH numbered AS(
SELECT row_number() OVER() AS row, entry
FROM mylist)
SELECT a.entry
FROM numbered AS a JOIN numbered AS b
ON a.row = b.row-1 AND b.entry = 'admin_centre';
will return only n240045827
.
How does it work? Well, I just took a straightforward approach to assigning order to the returned list by using row_number() OVER()
. In this example, I've used a CTE WITH...
to add the row after the fact, but in your case you could add it into your query like so:
...
SELECT ltrim(member, 'n')::bigint AS osm_id
FROM (
SELECT row_number() OVER() a AS row, unnest(members) AS member
FROM planet_osm_rels
...
Finally, I simply join this result to itself, comparing one row to the next by its row number, and looking for the 'admin_centre'
text entry.
Here's a SQL Fiddle for testing.
For your perusal:
Common Table Expressions
Window Functions
Edit
If you want to return all rows as column pairs, then use the following approach:
WITH numbered AS(
SELECT row_number() OVER() AS row, entry
FROM mylist)
SELECT a.entry, b.entry
FROM numbered AS a JOIN numbered AS b
ON a.row = b.row-1 AND a.row%2 = 1;
Also, here's a SQL Fiddle #2 for testing.
No. There is no way. I think there is a slight misconception of how things work.
Unlike functions, which store the function body as string (late binding!), a view parses the query and does not store the original text at all. All identifiers are resolved according to the current search_path
and only their internal OIDs are saved (early binding!). That's also why SELECT *
always resolves to the list of columns at the point in time when the VIEW
was created.
What you see in pgAdmin or other clients when looking at the definition of a VIEW
is a re-engineered SQL string. public.schedule
will always be public.schedule
and sally.schedule
will always be sally.schedule
(unless you rename table or schema). The (schema-qualified) names that are displayed are chosen such that the identifier is unambiguous with regard to the current search path.
This also shows when you change the names of columns, tables or schemas. The view keeps just working, because it does not depend on these attributions. The display of the definition is adapted dynamically.
Possible solution
If you want late binding you could use a function instead of a view and default to the current search path (one could SET
the search path for the scope of a function to avoid that effect precisely.)
So instead of:
CREATE VIEW v_mechanics_schedule AS
SELECT * FROM schedule s -- use aliases for short qualified column names in display
LEFT JOIN mechanics m USING (mechanic_id);
Without schema-qualification, table names are resolved according to the current search_path
at creation time.
You could:
CREATE FUNCTION f_mechanics_schedule()
RETURNS TABLE (...) AS -- you have to spell out columns
$func$
SELECT * FROM schedule s -- this is typically error prone
LEFT JOIN mechanics m USING(mechanic_id);
$func$ LANGUAGE SQL
Now, table names are resolved according to the search_path
at execution time. Note that the same does not apply to the return type ( RETURNS TABLE (...)
), which is determined at creation time. So this trick only works for compatible tables - the query has to return the same list of columns, only data types and the number of columns matter, column names are ignored (only the names in the definition of the return type are visible outside the function).
That's also why SELECT *
to return values in the function body is typically unreliable. If you change the definition of underlying tables, the function breaks: The defined return type remains the same, but SELECT *
resolves to a different column list ...
OTOH, if you declare a function as RETURNS SETOF some_table
(different syntax variant), a functional dependency is registered and the return type of the function is bound to the table definition, so SELECT * FROM some_table
would make more sense.
This is also the reason why it is unsafe to have SECURITY DEFINER
functions without fixing the search_path
: Any user with the TEMP
privilege can create a temp table that hides other tables because pg_temp
comes first in the search path by default ...
Related:
You really need to understand the underlying mechanisms to play with this.
Best Answer
You created a case sensitive table name (which is strongly discouraged) so now you need to use double quotes every time you access it:
I highly recommend to stop using those dreaded quoted identifies. Forget that double quotes exists when dealing with SQL.