Why is my postgres lateral subquery failing? - postgresql

I'm trying to run the following query with postgres's support for LATERAL subqueries:
with s as
(
select
tagValues ->> 'mode' as metric
, array_agg(id) as ids
from
metric_v3.v_series
where
name = 'node_cpu'
group by 1
)
select
t.starttime
, s.metric
, t.max
from
s, lateral (
select
d.starttime
, max(d.max) as max
from
metric_v3.gaugedata d
where
d.starttime >= '2020-01-17T00:00Z' AND d.starttime < '2020-01-24T00:00Z'
and d.seriesid in s.ids
group by 1
) t
order by 1,2;
It fails with, where s relates to the reference in the lateral subquery's where clause.
SQL Error [42601]: ERROR: syntax error at or near "s"
I have tried different methods for the lateral query, but I always get the same error. I don't know what I'm missing.
If I run the CTE expression and select s.* from it, I get the expected results, so that part is working fine.
I'm running Postgres 11.6 on CentOS.

You can't use IN with an array. You need to use the ANY operator:
and d.seriesid = any(s.ids)

Related

Knex query error undefined column using nested select with orderBy

In a Knex query I'm getting that a column is undefined and I don't know how to resolve
the query I have in Knex
this.builder.orderBy(
this.tx(messageTable)
.max(messageColumns.createdAt)
.where(messageColumns.conversationId, 'conversation.id')
, direction)
The undefined happen on the last part of the .where(messageColumns.conversationId, 'conversation.id')
the SQL I want to get it to work with Knex is as follow
SELECT
*
FROM
"conversation"
ORDER BY
(
SELECT
max("created_at")
FROM
"message"
WHERE
"conversation_id" = conversation.id)
DESC
The query is wrong , try to do this:
select c.* from conversation c
join (
select conversation_id, max("created_at") created_at
from message
group by conversation_id
) m on c.conversation_id = m.conversation_id
order by m.created_at DESC

why am I getting ERROR: syntax error at end of input?

I am keep getting 'syntax error at end of input' and don't know why.
What I want to do is divide result of disease by result of total with showing condition_id in disease section.
select disease.condition_id, (disease::float/total::float) as prevalence
from (
select condition_id, count(person_id)
from a.condition
where condition_id=316139
group by condition_id
) as disease
join (
select count(distinct person_id) as total
from a.person
)as total;
Can someone please help me with this?
Thanks!
I don't have an exact fix for your current syntax, but I would phrase this query as a join with an aggregation over the entire tables:
SELECT
COUNT(*) FILTER (WHERE c.condition_id = 316139) /
COUNT(DISTINCT p.person_id) AS prevalence
FROM a.person p
LEFT JOIN a.condition c
ON p.person_id = c.person_id;
The main reason for your error is the missing join condition. The join operator requires a join condition (defined using ON).
But given the structure of your query I think you don't actually want a inner join, but a cross join between the two.
Additionally the expression disease::float is trying to cast a complete row to a float value, not a single column. I assume you wanted to alias the count aggregate to something, e.g. count(person_id) as num_persons
Using total::float is also ambiguous as you have a sub-query alias with that name and a column with that name. That is highly confusing, you should avoid that.
select disease.condition_id,
(disease.num_person::float / total.total::float) as prevalence
from (
select condition_id, count(person_id) as num_person
from a.condition
where condition_id = 316139
group by condition_id
) as disease
cross join (
select count(distinct person_id) as total
from a.person
) as total

How to perform "a UNION b" when a and b are CTEs?

If I try to UNION (or INTERSECT or EXCEPT) a common table expression I get a syntax error near the UNION. If instead of using the CTE I put the query into the union directly, everything works as expected.
I can work around this but for some more complicated queries using CTEs makes things much more readable. I also just don't like not knowing why something is failing.
As an example, the following query works:
SELECT *
FROM
(
SELECT oid, route_group
FROM runs, gpspoints
WHERE gpspoints.oid = runs.start_point_oid
UNION
SELECT oid, route_group
FROM runs, gpspoints
WHERE gpspoints.oid = runs.end_point_oid
) AS allpoints
;
But this one fails with:
ERROR: syntax error at or near "UNION"
LINE 20: UNION
WITH
startpoints AS
(
SELECT oid, route_group
FROM runs, gpspoints
WHERE gpspoints.oid = runs.start_point_oid
),
endpoints AS
(
SELECT oid, route_group
FROM runs, gpspoints
WHERE gpspoints.oid = runs.end_point_oid
)
SELECT *
FROM
(
startpoints
UNION
endpoints
) AS allpoints
;
The data being UNIONed together is identical but one query fails and the other does not.
I'm running PostgreSQL 9.3 on Windows 7.
The problem is because CTEs are not direct text-substitutions and a UNION b is invalid SELECT syntax. The SELECT keyword is a mandatory part of the parsing and the syntax error is raised before the CTEs are even taken into account.
This is why
SELECT * FROM a
UNION
SELECT * FROM b
works; the syntax is valid, and then the CTEs (represented by a and b) are then used at the table-position (via with_query_name).
At least in SQL Server, I can easily do this - create two CTE's, and do a SELECT from each, combined with a UNION:
WITH FirstNames AS
(
SELECT DISTINCT FirstName FROM Person
), LastNames AS
(
SELECT DISTINCT LastName FROM Person
)
SELECT * FROM FirstNames
UNION
SELECT * FROM LastNames
Not sure if this works in Postgres, too - give it a try!

postgres WITH query claims no FROM-clause

I've written a simple query that uses a WITH clause, but I'm getting this error:
Error : ERROR: missing FROM-clause entry for table "cte"
Here's the query, where I'm clearly putting a FROM clause. I know this must be simple but I'm just not seeing what I've done wrong. Thanks.
WITH cte AS (
SELECT cident, "month"
FROM orders_extended io
WHERE io.ident = 1 -- 1 will be replaced with a function parameter
)
SELECT *
FROM orders_extended o
WHERE o.cident = cte.cident AND o."month" = cte."month"
ORDER BY o."month" DESC, o.cname
The message didn't lie.
WITH cte AS (
SELECT cident, "month"
FROM orders_extended io
WHERE io.ident = 1 -- 1 will be replaced with a function parameter
)
SELECT o.*
FROM orders_extended o
INNER JOIN cte ON (o.cident = cte.cident and o."month" = cte."month")
ORDER BY o."month" DESC, o.cname

Sum of Count in SQL Server BI

Am developing a report using the SQL Server BI Development Studio, when I try to create a function to sum the counts for StudentID, I get an error "Aggregate functions cannot be nested inside other aggregate functions"
The following is the expression am using:-
=Sum(Count(Fields!StudentID.Value))
How can I perform such a calculation?
You can do it this way
;With CountIds AS
(
SELECT COUNT(Fields!StudentID.Value) AS CountOfId FROM Table ...
)
SELECT Sum(CountOfId)
FROM CountIds
The "With" gives you the COUNT with the conditions that you want. Then you SUM it.
But I'm not quite sure the query returns what you want.. (Because when I test the query, it gives me the same result that a COUNT on all the table..) I think want you want to know is "How many Count you have".
If so, I would do it that way instead.
;With CountId AS
(
SELECT COUNT(Fields!StudentID.Value) AS CountOfId FROM Table ...
)
SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY CountOfId)
FROM CountIds
ORDER BY 1 DESC
Or simply:
;With CountId AS
(
SELECT COUNT(Fields!StudentID.Value) AS CountOfId FROM Table ...
)
SELECT COUNT(*) FROM CountIds