I'm after running a query with a subquery (perhaps inefficient) that using a regular expression pattern it can return how many instances of a characters are included with a given record.
In doing so, I came across something like:
SELECT t."page",
product_tree_length,
Count(*),
FROM "Table" t
,
LATERAL (SELECT (LENGTH((regexp_matches(t."page", '^.+\/c\/(.+?)(?=\/\?|\?|\/$).*$', 'g'))[1]) - LENGTH(REPLACE(((regexp_matches(t."page", '^.+\/c\/(.+?)(?=\/\?|\?|\/$).*$', 'g'))[1]),'/','')))) AS "product_tree_length"
where t.page like '%\/c/%'
GROUP BY 1, product_tree_length;
However, in selecting the product_tree_length in the main query, the returned data type is a record and not an integer as expected. If I try to cast the value, PostgreSQL raise an exception that the operation cannot be completed.
Any idea on what I am doing wrong?
Thanks
-
1Please show us the complete query (edit your question, do not post code in comments)user1822– user18222019年07月01日 18:44:43 +00:00Commented Jul 1, 2019 at 18:44
-
@a_horse_with_no_name query added above. Not sure if it really helps but worth a try.Andrea Moro– Andrea Moro2019年07月02日 08:28:04 +00:00Commented Jul 2, 2019 at 8:28
2 Answers 2
Well product_tree_length
is a table alias, not a column alias. So if you use that alias in the SELECT list, obviously you get a record.
You have two options to properly define an alias for the column
Solution one: use a column alias inside the derived table:
select t.page
product_tree_length.len,
count(*)
from "Table" t
cross join lateral (
SELECT length(....) as len
) AS product_tree_length
...
Solution two: define a column alias as part of the table alias:
select t.page
product_tree_length.len,
count(*)
from "Table" t
cross join lateral (
SELECT length(....)
) AS product_tree_length(len)
...
-
Thanks. Any advice on which is the best in term of performance?Andrea Moro– Andrea Moro2019年07月02日 08:49:32 +00:00Commented Jul 2, 2019 at 8:49
-
There is no difference in performance.user1822– user18222019年07月02日 08:50:19 +00:00Commented Jul 2, 2019 at 8:50
-
Thanks, your help was very appreciated. One more question. I noticed you used the CROSS JOIN as opposed me doing the FROM TABLE, LATERAL ... was that a mistake? Sorry to ask, but PostgreSQL is not my primary database.Andrea Moro– Andrea Moro2019年07月02日 08:56:01 +00:00Commented Jul 2, 2019 at 8:56
-
from a,b
is the same asfrom a cross join b
- I prefer the explicit use of CROSS JOIN to document that this is indeed what I intended. The cross join resulting fromfrom a,b
could have been an accident. (the use oflateral
doesn't really change that)user1822– user18222019年07月02日 08:57:16 +00:00Commented Jul 2, 2019 at 8:57 -
Makes sense. ThanksAndrea Moro– Andrea Moro2019年07月02日 13:34:07 +00:00Commented Jul 2, 2019 at 13:34
SELECT t."page",
Count(*),
(LENGTH((regexp_matches(t."page", '^.+\/c\/(.+?)(?=\/\?|\?|\/$).*$', 'g'))[1]) - LENGTH(REPLACE(((regexp_matches(t."page", '^.+\/c\/(.+?)(?=\/\?|\?|\/$).*$', 'g'))[1]),'/',''))) as product_tree_length FROM "Table" t where t.page like '%\/c/%' GROUP BY 1,3;
I think you don't need a lateral join here if you just wanted the length