Syntax error at or near 'Except' in postgresql - postgresql

Can someone help me find my syntax error? I feel like I've been staring at this stupid section for hours and have tried changing things, rewriting it, etc, but it just keeps giving me an error.
SELECT DISTINCT S.customer_name
FROM depositor AS S
WHERE NOT EXIST (
(SELECT branch_name
FROM branch
WHERE branch_city='Brooklyn')
EXCEPT
(SELECT R.branch_name
FROM depositor AS T, account AS R
WHERE T.account_number = R.account_number
AND S.customer_name = T.customer_name));

EXCEPT should be between two SELECTs, eg
SELECT ...
EXCEPT
SELECT ...
So your query should be:
SELECT DISTINCT S.customer_name
FROM depositor AS S
WHERE NOT EXISTS (
SELECT branch_name
FROM branch
WHERE branch_city='Brooklyn'
EXCEPT
SELECT R.branch_name
FROM depositor AS T, account AS R
WHERE T.account_number = R.account_number
AND S.customer_name = T.customer_name
)
I also removed the unnecessary brackets and corrected the spelling error of EXIST to EXISTS.

Related

PyCharm has outdated SQL dialects?

I'm working with PostgresQL database with a python script. I have a query like this:
UPDATE orders SET id=%s, client=%s, contents=%s, adress=%s, detail=%s, price=%s HAVING MIN(id)
It works fine, but PyCharm says that "having" statement doesn't exist and i should use "where" (while "where" gives an exception in this query because I'm using "MIN"). And I have SQL dialect in PyCharm set to "PostgresQL". Any ways to fix this annoying issue?
UPD: my bad, this query isn't working. It somehow didn't throw an exception in python, but the row in database wasn't updated. Then what query should I use to update row with the least id?
You can get min(id) in the same query with either a sub-query or a CTE. Perhaps something like:
update some_tbl
set col = 1
where id = (select min(id)
from some_tbl
) ;
OR
with lowers(mid) as
(select min(id)
from some_tbl
)
update some_tbl st
set col = 1
from lowers l
where st.id = l.mid;

Looking for equivalent in postgresql for merge update implemented in mssql

Have to migrate the below MSSQL code to postgresql
Looking forward for postgresql code which does the following.
MSSQL codee
MERGE TO_SubFamy AS TARGET
USING
(
SELECT SF.Id as SubFamyId,
CASE WHEN COUNT(A.Id)>0 THEN 'Young' ELSE 'OLD' END as ActiveYn
FROM
TO_SubFamy SF
RIGHT JOIN TO_SubFamyAutomationLink SFA ON SF.Id=SFA.SubFamyId
RIGHT JOIN TO_AUTOMATiON A ON A.Id = SFA.AutomationId and A.State='Active'
WHERE SF.Status <> 'not exits'
GROUP BY SF.Id
EXCEPT
SELECT Id, status from TO_SubFamy WHERE Status <> 'not exits'
) as SOURCE
ON TARGET.Id = SOURCE.SubFamyId
WHEN MATCHED THEN
UPDATE SET TARGET.status = SOURCE.ActiveYn;
pls help
My experience with MySql is rather limited, but the statement looks suspiciously like the same statement in Oracle. (Not a surprise as it wasn't supported until after Oracle bought MySql.) And a little research seems to confirm.
The merge statement is typically used to either insert or update based on the result of the ON statement. But another semi-common use is strictly to update as the syntax is somewhat easier in many cases as you do need to essentially repeat the select statement. Since your statement uses only the WHEN MATCHED clause it is the latter use being employed. So the translation is just a UPDATE. I think the follow satisfies your need.
with source (subfamyid,activeyn) as
(select sf.id,
case when count(a.id)>0 then 'Young' else 'OLD' end
from to_subfamy sf
right join to_subfamyautomationlink sfa on sf.id=sfa.subfamyid
right join to_automation a on a.id = sfa.automationid and a.state='Active'
where sf.status <> 'not exits'
group by sf.id
except
select id, status from to_subfamy where status <> 'not exits'
)
update to_subfamy as target
set status = source.activeyn
where target.id = source.subfamyid;
Disclaimer: As you neglected sample data and expected results the query has not been tested. However, right joins look suspicious, appears that all rows from table "to_automation" will be kept even if they do not exist in either of the others.

Postgres subquery has access to column in a higher level table. Is this a bug? or a feature I don't understand?

I don't understand why the following doesn't fail. How does the subquery have access to a column from a different table at the higher level?
drop table if exists temp_a;
create temp table temp_a as
(
select 1 as col_a
);
drop table if exists temp_b;
create temp table temp_b as
(
select 2 as col_b
);
select col_a from temp_a where col_a in (select col_a from temp_b);
/*why doesn't this fail?*/
The following fail, as I would expect them to.
select col_a from temp_b;
/*ERROR: column "col_a" does not exist*/
select * from temp_a cross join (select col_a from temp_b) as sq;
/*ERROR: column "col_a" does not exist
*HINT: There is a column named "col_a" in table "temp_a", but it cannot be referenced from this part of the query.*/
I know about the LATERAL keyword (link, link) but I'm not using LATERAL here. Also, this query succeeds even in pre-9.3 versions of Postgres (when the LATERAL keyword was introduced.)
Here's a sqlfiddle: http://sqlfiddle.com/#!10/09f62/5/0
Thank you for any insights.
Although this feature might be confusing, without it, several types of queries would be more difficult, slower, or impossible to write in sql. This feature is called a "correlated subquery" and the correlation can serve a similar function as a join.
For example: Consider this statement
select first_name, last_name from users u
where exists (select * from orders o where o.user_id=u.user_id)
Now this query will get the names of all the users who have ever placed an order. Now, I know, you can get that info using a join to the orders table, but you'd also have to use a "distinct", which would internally require a sort and would likely perform a tad worse than this query. You could also produce a similar query with a group by.
Here's a better example that's pretty practical, and not just for performance reasons. Suppose you want to delete all users who have no orders and no tickets.
delete from users u where
not exists (select * from orders o where o.user_d = u.user_id)
and not exists (select * from tickets t where t.user_id=u.ticket_id)
One very important thing to note is that you should fully qualify or alias your table names when doing this or you might wind up with a typo that completely messes up the query and silently "just works" while returning bad data.
The following is an example of what NOT to do.
select * from users
where exists (select * from product where last_updated_by=user_id)
This looks just fine until you look at the tables and realize that the table "product" has no "last_updated_by" field and the user table does, which returns the wrong data. Add the alias and the query will fail because no "last_updated_by" column exists in product.
I hope this has given you some examples that show you how to use this feature. I use them all the time in update and delete statements (as well as in selects-- but I find an absolute need for them in updates and deletes often)

postgres syntax error in sql

select * from (
select max(h.updated_datetime) as max, min(h.updated_datetime) as min from report r, report_history h, procedure_runtime_information PRI, study S
where
h.report_fk=r.pk and
r.study_fk=S.pk and
PRI.pk=S.procedure_runtime_fk and
extract(epoch from (max(h.updated_datetime) - min(h.updated_datetime) ) <=900 and
h.pk IN (
select pk from
(select * from report_history where report_fk=r.pk) as result
)
and r.status_fk =21 group by r.pk)as result1;
this is my query i have a syntax error can any one help me fix this
thanks in advance
As you didn't bother telling us what the error is I have to guess, that it's this line:
AND h.pk IN (SELECT pk FROM (SELECT * FROM report_history WHERE report_fk=r.pk) AS RESULT)
The nesting level for the where condition is "too deep" and I think it cannot see the r alias in the where clause.
But the nested select is totally useless in your case anyway, so you can rewrite that condition as:
AND h.pk IN (SELECT pk FROM report_history WHERE report_fk=r.pk)
Even if that doesn't solve your problem, it makes your query more readable.
Then you are using an aggregate in the where clause which is also not allowed, you have to move it to a having clause.
having extract(epoch from (max(h.updated_datetime) - min(h.updated_datetime))) <=900
The having clause comes after the group by
You were also missing a closing ) but that is hard to tell because of your formatting (which I find very hard to read)
You should also get used to explicit JOIN syntax. The implicit joins in the WHERE clause are error-prone and no longer recommended.

How to delete rows using an outer join

I've got a problem to delete records from a PostgreSQL table, using a LEFT JOIN.
I'd like to delete rows I get with the following query:
SELECT * FROM url
LEFT JOIN link_type ON url.link_type = link_type.id
WHERE link_type.id IS NULL
To do so, here is what I did:
DELETE FROM url
USING link_type
WHERE url.link_type = link_type.id AND link_type.id IS NULL
Query works but doesn't delete anything, although that's exactly what's explained in the doc: http://www.postgresql.org/docs/current/static/sql-delete.html.
Is my problem due to IS NULL in the query or Am I missing something?
Good work, sun. Minor suggestion: when using EXISTS/NOT EXISTS you don't need to SELECT *. A common convention (docs) is to just write SELECT 1 as like this:
DELETE FROM url WHERE NOT EXISTS (
SELECT 1 FROM link_type WHERE url.link_type = link_type.id
);
Functionally, both ways work.
Still don't understand why my previous query doesn't work (if someone could explain, would be nice), but here is how I did the trick:
DELETE FROM url WHERE NOT EXISTS (SELECT * FROM link_type WHERE url.link_type = link_type.id );