Postgres delete query - Syntax error near count(*) - postgresql

I want to delete records from F table which has only one H record and that record has thrown 76 errorkode.
I am getting syntax error as i am joining and doing the count(*) check . Is there any correct way to do it???
delete from F fb where id in(select h.id from H h
join MI m on h.m_i_id=m.id
join ERROR e on e.m_i_id=m.id
join ERRORKODE ek on e.errorkode_id=ek.id where errorkode=76) and
select count(*) from H h where h.f_id = fb.id) =1

The where clause of delete has two conditions separated by and, the second one is query which should be in parenthesis. There is missing left parenthesis (before select keyword).

Related

How can I trigger a [42P09] error (ambiguous alias)

I have tried several ways to trigger a 42P09 (ambiguous alias) error, but none of them succeeded.
This just "works", even when combined with group by x or order by x:
select 1x, 1x;
This also "works":
with t as (select 1x, 1x, 1x) select * from t;
select x from (with x as (select 1x) select x.x x from x group by x order by x) as x;
These only raise a [42712] (duplicate alias):
with t as (select 1x), t as (select 1x) select * from t;
with t as (select 1x, 1x) select * from t, t;
These only raise a [42702] (ambiguous column):
select x from (select 1x, 1x) as t;
with t1 as (select 1x), t2 as (select 1x) select x from t1, t2;
My google-foo didn't bring up any relevant results, either. I could only find mentions of this error existing, but noone seems to encounter it.
Is there any way to trigger a 42P09 error?
Based on #Adrian Klaver's answer, here's a SQL statement that actually yields a 42P09 error:
with t1 as (select 1x), t2 as (select 1y)
select * from t1 x CROSS JOIN
(t2 x CROSS JOIN lateral ( select * from t2 where t1.x = t2.y ) y) z;
If it helps, from source(backend/parser/parse_relation.c):
"
Search the query's table namespace for an RTE matching the
given unqualified refname. Return the RTE if a unique match, or NULL
if no match. Raise error if multiple matches.
Note: it might seem that we shouldn't have to worry about the possibility
of multiple matches; after all, the SQL standard disallows duplicate table
aliases within a given SELECT level. Historically, however, Postgres has
been laxer than that. For example, we allow
SELECT ... FROM tab1 x CROSS JOIN (tab2 x CROSS JOIN tab3 y) z
on the grounds that the aliased join (z) hides the aliases within it,
therefore there is no conflict between the two RTEs named "x". However,
if tab3 is a LATERAL subquery, then from within the subquery both "x"es
are visible. Rather than rejecting queries that used to work, we allow
this situation, and complain only if there's actually an ambiguous
reference to "x".
"

Adding row value after grouping the table causes * must appear in the GROUP BY clause

I am trying to join 2 tables like so:
left join (
select t1.createdate, min(f1.createdate) as mindt, f1.status_aft
from new_table t1
left join new_folder f1 on t1.veh_id = f1.veh_id
where f1.createdate > t1.createdate
group by t1.createdate
) h3
on t1.createdate = h3.createdate
and f1.createdate = h3.mindt
But I am getting an error:
ERROR: column "f1.status_aft" must appear in the GROUP BY clause or be used in an aggregate function
This makes sense because I do not group it, my goal is just to take the value that is in that current row when f1.createdate is min.
For example:
A B C
one 10 a
one 15 b
two 20 c
two 25 d
Becomes
A B C
one 10 a
two 20 c
Because a and c was the values when column B were the lowest after grouping it by column A.
I've seen this answer but I still can't apply it to my scenario.
How can I achieve the desired result?
my goal is just to take the value that is in that current row when f1.createdate is min.
If you want just one row, you can order by and limit:
left join (
select t1.t1.createdate, f1.createdate as mindt, f1.status_aft
from new_table t1
left join new_folder f1 on t1.veh_id = f1.veh_id
where f1.createdate > t1.createdate
order by t1.createdate limit 1
) h3

How to count total number of records after join the three tables in postgresql?

I have a query which gives me total 12408 records after executing but i want this give me total records as count column
select
c.complaint_id,c.server_time,c.completion_date,c.road_id,c.photo,c.dept_code,c.dist_code,c.eng_userid,c.feedback_type,c.status,p.dist_name,p.road_name,p.road_dept,e.display_name,e.mobile
from complaints as c INNER JOIN pwd_roads as p ON p.road_id=c.road_id
INNER JOIN enc_details as e ON CAST(e.enc_code as INTEGER) = p.enccode
where c.complaint_id=c.parent_complaint_id and c.dept_code='PWDBnR'
and c.server_time between '2018-09-03' and '2018-12-19'
You can solve this issue using window functions. For example, if you want your first columns to be a count of the total rows done by the SELECT statement:
select count(1) over(range between unbounded preceding and unbounded following) as total_row_count
, c.complaint_id,c.server_time,c.completion_date,c.road_id,c.photo,c.dept_code,c.dist_code,c.eng_userid,c.feedback_type,c.status,p.dist_name,p.road_name,p.road_dept,e.display_name,e.mobile from complaints as c INNER JOIN pwd_roads as p ON p.road_id=c.road_id INNER JOIN enc_details as e ON CAST(e.enc_code as INTEGER) = p.enccode where c.complaint_id=c.parent_complaint_id and c.dept_code='PWDBnR' and c.server_time between '2018-09-03' and '2018-12-19'
Note that the window function is evaluated before the LIMIT clause if one is used, so if you were to add LIMIT 100 to the query it might give a row count greater than 100 even though a max of 100 rows would be returned.
Easiest but not very elegant way to do this is:
select count(*)
from
(
select c.complaint_id,c.server_time,c.completion_date,c.road_id,c.photo,c.dept_code,c.dist_code,c.eng_userid,c.feedback_type,c.status,p.dist_name,p.road_name,p.road_dept,e.display_name,e.mobile from complaints as c INNER JOIN pwd_roads as p ON p.road_id=c.road_id INNER JOIN enc_details as e ON CAST(e.enc_code as INTEGER) = p.enccode where c.complaint_id=c.parent_complaint_id and c.dept_code='PWDBnR' and c.server_time between '2018-09-03' and '2018-12-19'
)

Getting error while retrieving data from a sub query and using that data source in another sub query above that

select id,proc_name,p_date,p_no,p_count
from (
(Select id,proc_name,p_date,p_no from aa) x
join
(select id,count(p_no) p_count from aa group by mrn) y
on x.id=y.id
) a
FROM (select id,proc_name,p_date,p_no from zz) aa
getting the error code 42601 at the position of FROM (in upper case).
A SELECT statement can only have one FROM clause.
Instead of using multiple FROM clauses, you should JOIN the tables.
There is no need to have two SELECTs from table aa, you can do that with a single SELECT using window functions:
SELECT id, proc_name, p_date, p_no,
count(p_no) OVER (PARTITION BY mrn) p_count
FROM aa;
You didn't tell over which columns you want to join aa and zz, but your statement could look something like this:
SELECT a.id, a.proc_name, a.p_date, a.p_no, a.p_count
FROM
(SELECT id, proc_name, p_date, p_no,
count(p_no) OVER (PARTITION BY mrn) p_count
FROM aa) a
JOIN zz
ON <join condition for a and zz>;

Postgres - using select statement inside CASE WHEN

Inside case when condition I am executing select statement & if returns anything then I need to get it's value but I am getting error
ERROR: missing FROM-clause entry for table "us"
query is..
SELECT u.user_id,
CASE
WHEN
(SELECT us.attr_value
FROM user_setting us
WHERE us.user_id = u.user_id) IS NOT NULL THEN us.attr_value
ELSE
(SELECT gus.attr_value
FROM global_user_setting gus
WHERE gus.attr_key='key')
END
FROM user u
WHERE u.user_id IN (1,
2,3)
Error comes at IS NOT NULL THEN us.attr_value I understood the issue but couldn't find how to get that value outside select statement?
Try:
COALESCE((SELECT us.attr_value
FROM user_setting us
WHERE us.user_id = u.user_id),
(SELECT us.attr_value
FROM global_user_setting gs
WHERE gus.attr_key='key'))
instead. The reason for the problem is, that the binding of the es alias is not visible outside of the sub-select (as it is used in a "scalar" context). The whole subselect is basically a single expression, which will yield a single value.
Another (IMHO better) approach would be to left-join on the enrollment_settings table:
SELECT u.user_id,
COALESCE(us.attr_value, (SELECT gus.attr_value
FROM global_user_setting gs
WHERE gus.attr_key='key'))
FROM user u LEFT JOIN user_settings es ON us.user_id = u.user_id
WHERE u.user_id IN (1, 2, 3)
I assume here, that this join would yield at most a single row per row of user.