SQL syntax error near rank() and any other window function - postgresql

I wrote a simple SQL query and it seems no matter what window function I use I get a syntax error for the () after any function. anyone have any ideas?
select emp_ssn, emp_status, appt_date,
rate_eff_dt, class_eff_dt
rank() OVER (
partition by emp_ssn
order by rate_eff_dt desc)
from pds_emp e
inner join pds_rate_new_vw r on e.emp_ssn = r.rate_emp_ssn
inner join pds_class_new c on e.emp_ssn = c.class_emp_ssn
where rate_eff_dt > '0/00/0000' and
class_eff_dt > '0/00/0000'
limit 1000

Related

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

Lateral query syntax

I'm trying to get lateral to work in a Postgres 9.5.3 query.
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id",
lateral (select ci."MaximumPlaces" - "EnrolledStudents") x
I want the right-most column to be the result of "MaximumPlaces" - "EnrolledStudents" for that row but am struggling to get it to work. At the moment PG is complaining that "EnrolledStudents" does not exist - which is exactly the point of "lateral", isn't it?
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
lateral (select "MaximumPlaces" - "EnrolledStudents") as "x"
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
If I try inlining the lateral clause (shown above) in the select it gets upset too and gives me a syntax error - so where does it go?
Thanks,
Adam.
You are missing the point with LATERAL. It can access columns in tables in the FROM clause, but not aliases defined in SELECT clause.
If you want to access alias defined in SELECT clause, you need to add another query level, either using a subquery in FROM clause (AKA derived table) or using a CTE (Common Table Expression). As CTE in PostgreSQL acts as an optimization fence, I strongly recommend going with subquery in this case, like:
select
-- get all columns on the inner query
t.*,
-- get your new expression based on the ones defined in the inner query
t."MaximumPlaces" - t."EnrolledStudents" AS new_alias
from (
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
) t

JOIN tables inside a subquery in DB2

I'm having trouble with paginating with joined tables in DB2. I want to return rows 10-30 of a query that contains an INNER JOIN.
This works:
SELECT *
FROM (
SELECT row_number() OVER (ORDER BY U4SLSMN.SLNAME) AS ID,
U4SLSMN.SLNO, U4SLSMN.SLNAME, U4SLSMN.SLLC
FROM U4SLSMN) AS P
WHERE P.ID BETWEEN 10 AND 30
This does not work:
SELECT *
FROM (
SELECT row_number() OVER (ORDER BY U4SLSMN.SLNAME) AS ID,
U4SLSMN.SLNO, U4SLSMN.SLNAME, U4SLSMN.SLLC, U4CONST.C4NAME
FROM U4SLSMN INNER JOIN U4CONST ON U4SLSMN.SLNO = U4CONST.C4NAME
) AS P
WHERE P.ID BETWEEN 10 AND 30
The error I get is:
Selection error involving field *N.
Note that the JOIN query works correctly by itself, just not when it's run as a subquery.
How do I perform a join inside a subquery in DB2?
Works fine for me on v7.1 TR9
Here's what I actually ran:
select *
from ( select rownumber() over (order by vvname) as ID, idescr, vvname
from olsdta.ioritemmst
inner join olsdta.vorvendmst on ivndno = vvndno
) as P
where p.id between 10 and 30;
I much prefer the CTE version however:
with p as
( select rownumber() over (order by vvname) as ID, idescr, vvname
from olsdta.ioritemmst
inner join olsdta.vorvendmst on ivndno = vvndno
)
select *
from p
where p.id between 10 and 30;
Finally, note that at 7.1 TR11 (7.2 TR3), IBM added support of the LIMIT and OFFSET clauses. Your query could be re-done as follows:
SELECT
U4SLSMN.SLNO, U4SLSMN.SLNAME, U4SLSMN.SLLC, U4CONST.C4NAME
FROM U4SLSMN INNER JOIN U4CONST ON U4SLSMN.SLNO = U4CONST.C4NAME
ORDER BY U4SLSMN.SLNAME
LIMIT 20 OFFSET 9;
However, note that the LIMIT & OFFSET clauses are only supported in prepared or embedded SQL. You can't use them in STRSQL or STRQMQRY. I believe the "Run SQL Scripts" GUI interface does support them. Here's an article about LIMIT & OFFSET

Get maximum value of an aggregate function

I want to only return the row where the count(object) is the highest, so I have written this query
select klantnr, count(objectnaam)
from klanten inner join deelnames using(klantnr)
inner join reizen using(reisnr)
inner join bezoeken using(reisnr)
where objectnaam = 'Maan'
group by klantnr
Now, I can't do
select max(count(objectnaam))
How would I go about solving this problem?
I have tried by using a subquery which is equally invalid
select max(select count(objectnaam) from ....)
I think I need a subquery in the from, so I have rewritten the query like this which I think is closer to the actual answer but still not right, as now it returns the maximum value of all rows.
select klantnr, max(c)
FROM(
select klantnr, count(objectnaam) as c
from klanten inner join deelnames using(klantnr)
inner join reizen using(reisnr)
inner join bezoeken using(reisnr)
where objectnaam = 'Maan'
group by klantnr) as F
group by klantnr
thanks for any help you can give me!
You do not provide the structure of tables, so probably you have to modify the following query. However it works just for PostgreSQL 9.x+
WITH t AS (
SELECT klantnr, COUNT(objectnaam) AS c
FROM klanten
WHERE objectnaam = 'Maan'
GROUP BY klantnr
ORDER BY c DESC
LIMIT 1
)
SELECT * FROM t
INNER JOIN deelnames USING(klantnr)
INNER JOIN reizen USING(reisnr)
INNER JOIN bezoeken USING(reisnr);
see http://www.postgresql.org/docs/9.3/static/queries-with.html how to use WITH QUERIES.
I have found a simpeler solution:
select klantnr,count (klantnr)
from bezoeken natural join deelnames
where objectnaam ='Maan'
group by klantnr
order by count desc
limit 1

Help with RANK() Over Scalar Function - SQL Server 2008

I have the following Inline Table-Valued Function:
SELECT Locations.LocationId,
dbo.Search_GetSuitability(#SearchPreferences,
Score.FieldA, Score.FieldB, Score.FieldC) AS OverallSuitabilityScore,
RANK() OVER (ORDER BY OverallSuitabilityScore) AS OverallSuitabilityRank
FROM dbo.LocationsView Locations
INNER JOIN dbo.LocationScores Score ON Locations.LocationId = Score.LocationId
WHERE Locations.CityId = #LocationId
That RANK() line is giving me an error:
Invalid column name 'OverallSuitabilityScore'.
The function dbo.Search_GetSuitability is a scalar-function which returns a DECIMAL(8,5). I need to assign a rank to each row based on that value.
The only way i can get the above to work is to add the scalar function call in the ORDER BY part again - which is silly. I have about 5 of these scalar function calls and i need seperate RANK() values for each.
What can i do? Can i use a Common Table Expression (CTE) ?
Yep, you can't reference a column alias in the SELECT clause. The CTE sounds good though. Here's an example
WITH Score as
(
select Score.LocationId, Score.FieldA, Score.FieldB, Score.FieldC,
dbo.Search_GetSuitability(#SearchPreferences,
Score.FieldA, Score.FieldB, Score.FieldC) AS OverallSuitabilityScore
from dbo.LocationScores
)
SELECT TOP(10)
Locations.LocationId,
Score.OverallSuitabilityScore,
RANK() OVER (ORDER BY OverallSuitabilityScore) AS OverallSuitabilityRank
FROM dbo.LocationsView Locations
INNER JOIN Score ON Locations.LocationId = Score.LocationId
WHERE Locations.CityId = #LocationId
An old school way of doing this is just to SUBQUERY the expression.
The CTE here only moves the subquery to the top
SELECT TOP(10) LocationId,
OverallSuitabilityScore,
RANK() OVER (ORDER BY OverallSuitabilityScore) AS OverallSuitabilityRank
FROM
(
SELECT
Locations.LocationId,
dbo.Search_GetSuitability(#SearchPreferences,
Score.FieldA, Score.FieldB, Score.FieldC) AS OverallSuitabilityScore
FROM dbo.LocationsView Locations
INNER JOIN dbo.LocationScores Score ON Locations.LocationId = Score.LocationId
WHERE Locations.CityId = #LocationId
) X