I am designing a comment reply model in golang and Postgres, and my comment table looks like this.
create TABLE comments(postid uuid DEFAULT uuid_generate_v4 (),
comment TEXT,
comment_reaction VARCHAR(255) NOT NULL,
commented_user VARCHAR(255) NOT NULL,
created_at TIMESTAMP,
parent_path ltree ,
CONSTRAINT fk_post FOREIGN KEY(postid)
REFERENCES posts(postid) on DELETE CASCADE);
I have added a couple of values to the table and my selection goes as below:
SELECT * FROM comments WHERE parent_path <# 'ed9f0f769ee4455b8dbf6120afc902fa';
postid | comment | comment_reaction | commented_user | created_at | parent_path
--------------------------------------+----------+------------------+----------------+----------------------------+--------------------------------------
ed9f0f76-9ee4-455b-8dbf-6120afc902fa | blah1 | | sai | 2021-02-06 16:46:36.436241 | ed9f0f769ee4455b8dbf6120afc902fa
ed9f0f76-9ee4-455b-8dbf-6120afc902fa | reply1 | | sai | 2003-02-01 00:00:00 | ed9f0f769ee4455b8dbf6120afc902fa.1
ed9f0f76-9ee4-455b-8dbf-6120afc902fa | reply2 | | sai | 2003-02-01 00:00:00 | ed9f0f769ee4455b8dbf6120afc902fa.2
ed9f0f76-9ee4-455b-8dbf-6120afc902fa | reply1.1 | | sai | 2003-02-01 00:00:00 | ed9f0f769ee4455b8dbf6120afc902fa.1.2
so basically I have some post with id
which has a comment. blah1 whose replies are reply 1 and reply 2 and reply 1 has sub reply reply1.1
How do I map it to a struct in go such that I get a JOSN output as below
{
post :ed9f0f76-9ee4-455b-8dbf-6120afc902fa,
comment :blah
reply1 :{
comment:reply1,
reply: {
comment :reply1.1
}
}
reply2 :{
comment:reply2,
}
}
so this can go to n comment and reply, is it even possible in the first place to reconstruct the JSON mapping in go? and if yes can someone help me? Alternate solutions for a schema and reconstruction are also appreciated.
so, i figured a solution myself while trying to understand facebook schema.
facebook shows the first level comments and shows the replies but replies are hidden.
so we can do BFS on the tree
SELECT * FROM comments WHERE parent_path ~ 'be785c64e9654a59821d20dff67230fc.*{1,1}';
this gives us first level children, which i can map to a struct and show the replies for each child as count
Then if user wants to dig in he can make another api call with the child node.
This way performance is also preserved. mapping entire tree to struct recursively will also affect the performance.
I'm trying to find distinct on one column and I want to make output to Upper
select
DISTINCT ON (UPPER(approver_wwid)) approver_wwid ,
approver_name
from cons_temp
I'm using Distinct on because name is ambiguous while wwid can be distinct.
I just want to output value of approver_wwid in upper.
Sample Data
approver_wwid | approver_name
ab123 | Jhon Mark
AB123 | Jhon Mark
ab123 | Mark Jhon
CD123 | Dev Tim
cd123 | Dev Tim
Expected Output
approver_wwid | approver_name
AB123 | Jhon Mark
CD123 | Dev Tim
This will make your first column upper:
SELECT
DISTINCT ON (approver_wwid) UPPER(approver_wwid) AS approver_wwid,
approver_name
FROM cons_temp
But note, that it is not under your control which row will be returned.
In your case it could be 'Mark Jhon' or 'Jhon Mark' for the second column.
I have a table displaying information for the top four ratings of produce in a store. I want to be able to find specific products in this rating table. Here is a structure of the table
----------------------------------------------------------------------------
sectId | product_code | product_category | consumer_raniking
10444 | 11222 | PRODUCE | RATING_1
10444 | 45555 | PRODUCE | RATING_1
10444 | 10005 | PR0DUCE | RATING_1
20555 | 11344 | PRODUCE | RATING_2
20555 | 94003 | PRODUCE | RATING_2
... and so on.
I wrote a rule to find inserted products which ins not working the way I want, i.e. to find the targetted fact that was inserted into the table. Here is the rule I put together:
rule "find by product codes rating_1"
when
$product_table: ProductRanking( $rank1: this.getProductCodesRankFirst())
$product1 : Product( this.product_code memberOf $rank1, $product_code: product_code )
$product2 : Product( this.product_code == 10444,this.product_code != $product_code ,$product_code2: product_code)
then
System.out.println("Found Products for product_codes "+$product_code+ " "+$product_code2 ) ;
end
Unfortunately, this returns 3 rows. I inserted into the session the product in row 2 i.e. product with ocde 45555 and it does find row 2. However, ir also brings in row 1 and row3.
I can see why it's doing that. It's because the skus are in the sectId with sectId 10444. However, I want to only bring in the row
that I inserted, which is sectionId(10444), product_code(45555). How can I achieve that?
I solved it by using a global to filter out the extra products. In the first line that brings the rankings, I eliminate the extra-matching products this way:
global ProductHelper productHelper
$product_table: ProductRanking( $rank1: productHelper.getProductCodesRankFirst(),
productCode != productHelper.getProductCodeFruitCategory() && productCode!=
productHelper.productCodeVegetableCategory())
The ProductHelper identifies the product codes I want to eliminate and hence the extra 2 products brought in are ignored, creating a single match. I'm sure there is a better way, but since I'm no expert, this is what I was able to come up with.
Here is my table (simplified, only significant columns):
CREATE TABLE details(
id serial primary key,
name text,
Address jsonb );
And some sample Data
# Select * from details
id | name | Address
----+----------+-----------------------------------------------------------
1 | Batman | {"city":"Gotham City","street":"1007 Mountain Drive"}
2 | Superman | {"city":"Metropolis","street":"344 Clinton Street"}
3 | Flash | {"city":"Central City","street":"122 Englewood street"}
Now I would like to select only name and City field of Address, Query would be
Select name, Address -> 'city' as Address from details
name | Address
----------+------------------
Batman | "Gotham City"
Superman | "Metropolis"
Flash | "Central City"
But I want it to be filtered as shown below.
name | Address
----------+-------------------------
Batman | {"city":"Gotham City"}
Superman | {"city":"Metropolis"}
Flash | {"city":"Central City"}
Is it possible to select only some fields from jsonb type column? If it is possible then what would be the query ?
If you want to include only 1 field, your query can be fairly easy:
select name, jsonb_build_object('city', address -> 'city') address
from details
However, if you want to include multiple fields, things will get complex. You could f.ex. remove unwanted keys one-by-one with the - operator, like: jsonb_column - 'key1' - 'key2':
select name, address - 'street' address
from details
But this will only work, when you have a fairly few fields inside of the JSON column (and they are well defined).
If you want a general solution, you should use some aggregation:
select name, (select jsonb_object_agg(e.key, e.value)
from jsonb_each(address) e
where e.key in ('city')) address
from details
Sorry if the post is in fact a duplicate. Just could not google anything similar and I am bit stuck on approach.
I am trying to populate cells in one sheet depending on date in rows of a different sheet, like these:
Sheet1 - entry sheet
ID | Name | Start date | End date
10 | Mike | 1.06.2016 | 2.06.2016
13 | Dido | 1.06.2016 | 5.06.2016
8 | Rene | 2.06.2016 | 20.06.2016
Sheet2 - report sheet
ids/dates | 1.06.2016 | 2.06.2016 | 3.06.2016 | date+1
8 | | Rene | Rene | Rene
10 | Mike | Mike | |
13 | Dido | Dido | Dido | Dido
Column Name cell's are to be populated in sheet2 depending on Sheet1 Column ID, Start date, end date. The position of the populated cell is defined in sheet2 by column ID and row Dates that should equal the same values in sheet1.
This report could be done with help of one formula. Please, check this Example File.
Assumptions
Suppose, you have Sheet1 with data:
Col A: ID
Col B: Name
Col C: Start date
Col D: End Date
Case 1. ID's are unique.
Go to Sheet2 and paste this formula in it:
={{"ids/dates";filter(Sheet1!A2:A,Sheet1!A2:A<>"")},{ArrayFormula(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1));ArrayFormula(if(--(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1)>=filter(Sheet1!C2:C,Sheet1!C2:C<>0))*--(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1)<=filter(Sheet1!D2:D,Sheet1!C2:C<>0))=1,VLOOKUP(FILTER(Sheet1!A2:A,Sheet1!A2:A<>""),Sheet1!A:B,2,0),""))}}
That's all. Report will expand automatically when new data arrives on Sheet1. The report will return error if Data is not complete (misssing Names or dates) on Sheet1.
Case 2. ID's are NOT unique.
This solution works when ID's are not unique, ID's will be grouped together. One ID belongs to one person in this case.
The formula will be a bit longer:
={{"ids/dates";sort(UNIQUE(filter(Sheet1!A2:A,Sheet1!A2:A<>"")))},{ArrayFormula(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1));ArrayFormula(if(QUERY(QUERY({filter(Sheet1!A2:A,Sheet1!A2:A<>""),ArrayFormula((--(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1)>=filter(Sheet1!C2:C,Sheet1!C2:C<>0))*--(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1)<=filter(Sheet1!D2:D,Sheet1!C2:C<>0))))},"select Col1, sum(Col"&JOIN("), sum(Col",ArrayFormula(COLUMN(OFFSET(B2,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))))&") group by Col1"),"Select Col"&JOIN(", Col",ArrayFormula(COLUMN(OFFSET(B2,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))))&" where Col1>0",0)=1,VLOOKUP(sort(UNIQUE(filter(Sheet1!A2:A,Sheet1!A2:A<>""))),Sheet1!A:B,2,0),""))}}
See example here.
Case 3. IDs are NOT unique. One ID <> one name
Here's working example, please check it. This case is the hardest one. We can have multiple IDs referring to multiple names. The final formula:
={{"ids/dates",ArrayFormula(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1))};{sort(UNIQUE(FILTER(Sheet1!A2:A,Sheet1!A2:A<>""))),ArrayFormula(IFERROR(VLOOKUP(QUERY(QUERY({FILTER(Sheet1!A2:B,Sheet1!A2:A<>""),ArrayFormula(--(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1)>=filter(Sheet1!C2:C,Sheet1!C2:C<>0))*--(add(MIN(Sheet1!C:D),COLUMN(OFFSET(A1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))-1)<=filter(Sheet1!D2:D,Sheet1!C2:C<>0))*row(OFFSET(A1,,,rows(FILTER(Sheet1!A2:B,Sheet1!A2:A<>"")))))},"select Col1, sum(Col"&JOIN("), sum(Col",ArrayFormula(COLUMN(OFFSET(C1,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))))&") group by Col1"),"Select Col"&JOIN(", Col",ArrayFormula(COLUMN(OFFSET(B2,,,1,MAX(Sheet1!C:D)-MIN(Sheet1!C:D)))))&" where Col1>0",0),{ArrayFormula(row(OFFSET(A1,,,rows(FILTER(Sheet1!A2:B,Sheet1!A2:A<>""))))),FILTER(Sheet1!A2:B,Sheet1!A2:A<>"")},3,0)))}}
The formula will work incorrectly if two Date ranges intersect:
102 Mike 6/21/2016 6/27/2016
102 Mike 6/11/2016 6/22/2016