Apache AGE - How to delete a label table properly? - postgresql

From AGE's source code, there is a function from the label_commands.c file which is called drop_label and I suppose that it deletes the table containing the label name. However, when I delete a vertex that is the only vertex of a label, it's table still appears at ag_catalog.ag_label (which stores all the available labels present in the graphs).
Here is the ag_catalog.ag_label table before deleting the only vertex from demo."Comic":
demo=# SELECT * FROM ag_catalog.ag_label;
name | graph | id | kind | relation | seq_name
------------------+-------+----+------+-----------------------+-------------------------
_ag_label_vertex | 16940 | 1 | v | demo._ag_label_vertex | _ag_label_vertex_id_seq
_ag_label_edge | 16940 | 2 | e | demo._ag_label_edge | _ag_label_edge_id_seq
Person | 16940 | 3 | v | demo."Person" | Person_id_seq
Book | 16940 | 4 | v | demo."Book" | Book_id_seq
Comic | 16940 | 5 | v | demo."Comic" | Comic_id_seq
Author | 16940 | 6 | v | demo."Author" | Author_id_seq
AUTHOR_OF | 16940 | 7 | e | demo."AUTHOR_OF" | AUTHOR_OF_id_seq
Store | 16940 | 8 | v | demo."Store" | Store_id_seq
(8 rows)
Deleting the vertex:
demo=# SELECT * FROM cypher('demo', $$
demo$# MATCH (v:Comic)
demo$# DETACH DELETE v
demo$# $$) as (v agtype);
Showing the contents of demo."Comic" afterwards:
demo=# SELECT * FROM demo."Comic";
id | properties
----+------------
(0 rows)
Since all the vertices of this label were removed, shouldn't this label also have been deleted and not even show this table? If not, how can I delete this label with cypher commands?

You can use the drop label function.
SELECT drop_label('graph_name','label_name');
Do note that this is not a cypher command, rather an AGE-specific function.

Related

how to write a trigger function which will check three columns in a same record?

in my table key_m, there are 4 columns operation which is char(1),token_type varchar(4) which will hold value soft or hard, department_code varchar(20), and last column default boolean
while inserting the record in key_m it should check(operation,token_typr, and department_code) that the values we are trying to insert are already present or not if not present then default should be true else it should be false.
for the first unique record insertion default value should be true, for the duplicate record entry value should be false.
example:-
| department_code | operation | token_type | ----- default|
| 1 | e | soft | t |
| 1 | e | hard | t |
| 1 | e | soft | f |
| 1 | e | hard | f |
| 1 | e | soft | f |
| 1 | e | soft | f |

Create a PostgreSQL function that becomes a formula field of a table retrieving related data from other table

The example above can be done on a SQL Server. It is a function that performs the calculation on another table while getting the current table field Id to list data from other table, return a single value.
Question: how to do the exact thing with PostgreSQL
SELECT TOP(5) * FROM Artists;
+------------+------------------+--------------+-------------+
| ArtistId | ArtistName | ActiveFrom | CountryId |
|------------+------------------+--------------+-------------|
| 1 | Iron Maiden | 1975-12-25 | 3 |
| 2 | AC/DC | 1973-01-11 | 2 |
| 3 | Allan Holdsworth | 1969-01-01 | 3 |
| 4 | Buddy Rich | 1919-01-01 | 6 |
| 5 | Devin Townsend | 1993-01-01 | 8 |
+------------+------------------+--------------+-------------+
SELECT TOP(5) * FROM Albums;
+-----------+------------------------+---------------+------------+-----------+
| AlbumId | AlbumName | ReleaseDate | ArtistId | GenreId |
|-----------+------------------------+---------------+------------+-----------|
| 1 | Powerslave | 1984-09-03 | 1 | 1 |
| 2 | Powerage | 1978-05-05 | 2 | 1 |
| 3 | Singing Down the Lane | 1956-01-01 | 6 | 3 |
| 4 | Ziltoid the Omniscient | 2007-05-21 | 5 | 1 |
| 5 | Casualties of Cool | 2014-05-14 | 5 | 1 |
+-----------+------------------------+---------------+------------+-----------+
The function
CREATE FUNCTION [dbo].[ufn_AlbumCount] (#ArtistId int)
RETURNS smallint
AS
BEGIN
DECLARE #AlbumCount int;
SELECT #AlbumCount = COUNT(AlbumId)
FROM Albums
WHERE ArtistId = #ArtistId;
RETURN #AlbumCount;
END;
GO
Now, (at SQL Server), after update the first table fields with ALTER TABLE Artists ADD AlbumCount AS dbo.ufn_AlbumCount(ArtistId); whe can list and get the following result.
+------------+------------------+--------------+-------------+--------------+
| ArtistId | ArtistName | ActiveFrom | CountryId | AlbumCount |
|------------+------------------+--------------+-------------+--------------|
| 1 | Iron Maiden | 1975-12-25 | 3 | 5 |
| 2 | AC/DC | 1973-01-11 | 2 | 3 |
| 3 | Allan Holdsworth | 1969-01-01 | 3 | 2 |
| 4 | Buddy Rich | 1919-01-01 | 6 | 1 |
| 5 | Devin Townsend | 1993-01-01 | 8 | 3 |
| 6 | Jim Reeves | 1948-01-01 | 6 | 1 |
| 7 | Tom Jones | 1963-01-01 | 4 | 3 |
| 8 | Maroon 5 | 1994-01-01 | 6 | 0 |
| 9 | The Script | 2001-01-01 | 5 | 1 |
| 10 | Lit | 1988-06-26 | 6 | 0 |
+------------+------------------+--------------+-------------+--------------+
but how to achieve this on postgresql?
Postgres doesn't support "virtual" computed column (i.e. computed columns that are generated at runtime), so there is no exact equivalent. The most efficient solution is a view that counts this:
create view artists_with_counts
as
select a.*,
coalesce(t.album_count, 0) as album_count
from artists a
left join (
select artist_id, count(*) as album_count
from albums
group by artist_id
) t on a.artist_id = t.artist_id;
Another option is to create a function that can be used as a "virtual column" in a select - but as this is done row-by-row, this will be substantially slower than the view.
create function album_count(p_artist artists)
returns bigint
as
$$
select count(*)
from albums a
where a.artist_id = p_artist.artist_id;
$$
language sql
stable;
Then you can include this as a column:
select a.*, a.album_count
from artists a;
Using the function like that, requires to prefix the function reference with the table alias (alternatively, you can use album_count(a))
Online example

PostgreSQL - How to do a Loop on a column

I am struggling to do a loop on a Postgres, but functions on postgres are not my piece of cake.
I have the following table on postgres:
| portfolio_1 | total_risk |
|----------------|------------|
| Top 10 Bets | |
| AAPL34 | 2,06699 |
| DISB34 | 1,712684 |
| PETR4 | 0,753324 |
| PETR3 | 0,087767 |
| VALE3 | 0,086346 |
| LREN3 | 0,055108 |
| AMZO34 | 0,0 |
| Bottom 10 Bets | |
| AAPL34 | 0,0 |
What I'm trying to do is get the values after the "Top 10 Bets" and before the "Botton 10 Bets".
My goal is the following result:
| portfolio_1 | total_risk |
|-------------|------------|
| AAPL34 | 2,06699 |
| DISB34 | 1,712684 |
| PETR4 | 0,753324 |
| PETR3 | 0,087767 |
| VALE3 | 0,086346 |
| LREN3 | 0,055108 |
| AMZO34 | 0,0 |
So, my goal is to take off the "Top 10 Bets", the "Botton 10 Bets" and the AAPL34 after the "Botton 10 Bets", which was repeated.
The quantity of rows is variable (I'm importing it from an Excel file), so I need a loop to do this, right?
SQL tables and result sets represent unordered sets. There is no "before" or "after" unless rows explicitly provide that information.
Let me assume that you have such a column, which I will call id for convenience.
Then you can do this in several ways. Here is one:
select t.*
from t
where t.id > (select min(t2.id) from t t2 where t2.portfolio_1 = 'Top 10 Bets') and
t.id < (select max(t2.id) from t t2 where t2.portfolio_1 = 'Bottom 10 Bets');

postgres sql : getting unified rows

I have one table where I dump all records from different sources (x, y, z) like below
+----+------+--------+
| id | source |
+----+--------+
| 1 | x |
| 2 | y |
| 3 | x |
| 4 | x |
| 5 | y |
| 6 | z |
| 7 | z |
| 8 | x |
| 9 | z |
| 10 | z |
+----+--------+
Then I have one mapping table where I map values between sources based on my usecase like below
+----+-----------+
| id | mapped_id |
+----+-----------+
| 1 | 2 |
| 1 | 9 |
| 3 | 7 |
| 4 | 10 |
| 5 | 1 |
+----+-----------+
I want merged results where I can see only unique results like
+-----+------------+
| id | mapped_ids |
+-----+------------+
| 1 | 2,9,5 |
| 3 | 7 |
| 4 | 10 |
| 6 | null |
| 8 | null |
+-----+------------+
I am trying different options but could not figure this out, is there way I can write joins to do this. I have to use the mapping table where associations are stored and identify unique records along with records which are not mapped anywhere.
My understanding is, you want to see all dump_table IDs that do not appear in the mapping_id column and then aggregate the mapped_ids for those that are left:
select d1.id,
array_agg(m1.mapped_id order by m1.mapped_id) filter (where m1.mapped_id is not null) as mapped_ids
from dump_table d1
left join mapping_table m1 using (id)
where not exists (select *
from mapping_table m2
where m2.mapped_id = d1.id)
group by d1.id;
Online example: https://rextester.com/JQZ17650
Try something like this:
SELECT id, name, ARRAY_AGG(mapped_id) AS mapped_ids
FROM table1 AS t1
LEFT JOIN table2 AS t2 USING (id)
GROUP BY id, name

postgresql condition column name = data

I have three tables.
table a
| uid | name | number |
|-----+---------+--------|
| 1 | table | 1 |
| 2 | chair | 2 |
table b
| uid | name | number |
|-----+---------+--------|
| 1 | john | 1 |
| 2 | billy | 0 |
| 3 | bob | 2 |
| 4 | sally | 1 |
table c
| uid | table a | john | billy | bob | sally |
|-----+---------+--------+--------+-------|-------|
| 1 | table | T | | | T |
| 2 | chair | | | C | |
What I need to be able to do is look at the column names in table c, find the corresponding row entry in table b and if the numbers are the same as the numbers from table a, then set the table c value to T. Otherwise set it to C. This needs to be triggered whenever either table a or table b are updated.
How can I write an update the table using if or case statement.
Thanks.