Sql - "missing right parenthesis" error explanation - sql

My code is syntactically correct and I don't think that I need any parenthesis,
however it keeps coming up with an error "00907. 00000 - "missing right parenthesis"" without any explanation of the cause
SELECT DISTINCT BG.name
FROM Brand_Group BG
WHERE BG.pid=(SELECT P.pid
FROM Indicia_Publisher IP
LEFT JOIN Publisher P ON IP.pid=P.pid
WHERE (IP.cid=(SELECT Country.cid
FROM Country
WHERE Country.name='Belgium') AND ROWNUM<=1)
GROUP BY P.pid
ORDER BY COUNT(P.pid));

The issue is to do with the ORDER BY in the comparison subquery - it's not valid syntax, which you can see by running the following query:
SELECT * FROM dual WHERE dummy IN (SELECT dummy FROM dual ORDER BY dummy);
Remove the ORDER BY clause and your query should run without issue.
Also, if you're wanting to get distinct rows returned and you're not using an aggregate function (e.g. MAX, SUM, etc), then you should use DISTINCT, not GROUP BY - it makes your intention much clearer. However, since you've restricted the results to a single row with and rownum = 1, there's not much point in using either!
Your query should probably be something along the lines of:
SELECT DISTINCT bg.name
FROM brand_group bg
WHERE bg.pid = (SELECT p.pid
FROM indicia_publisher ip
LEFT JOIN publisher p
ON ip.pid = p.pid
WHERE ip.cid = (SELECT country.cid
FROM country
WHERE country.name = 'Belgium') AND rownum <= 1);
ETA: I see that I misread your original SQL slightly and misinterpreted what you were after. It looks like you're after the p.pids with the highest count, so the following should do what you're after:
SELECT DISTINCT bg.name
FROM brand_group bg
WHERE bg.pid = (SELECT p.pid
FROM (SELECT p.pid,
COUNT(*) cnt,
MAX(COUNT(*)) OVER (PARTITION BY p.id) max_cnt
FROM indicia_publisher ip
LEFT JOIN publisher p
ON ip.pid = p.pid
WHERE ip.cid = (SELECT country.cid
FROM country
WHERE country.name = 'Belgium')
GROUP BY p.pid)
WHERE cnt = max_cnt
AND ROWNUM = 1);
If there are two or more different p.pids that have the highest count, the and rownum = 1 ensures only one will be picked (but it'll be random). May you want to use IN rather than = in the outer query's comparison, and that would remove the need for the rownum = 1 predicate.

is this Oracle, SQL Server? Oracle does not use left, Sql server does not have rownum. Do you expect one or more value to be return in subquery. it looks like more than 1. Then change BG.cid = () to ip.cid in (). Do you need the group in that subquery. You don't have count in that subquery.
I suggest you execute subquery one by one to find out what happens
Your original one has mixed of syntax (oracle/SqL server). I am going assume this is Oracle database
SELECT DISTINCT BG.name
FROM Brand_Group BG
WHERE BG.pid in
(SELECT P.pid
FROM Indicia_Publisher IP
WHERE
IP.pid=P.pid (+) and
(IP.cid=(SELECT Country.cid
FROM Country
WHERE Country.name='Belgium') AND ROWNUM<=1)
);

Related

Display only maximum value in query with column meno - SQL

As mentioned in the title I want to display only row with maximum number, for this case it´s number 4 and nothing less.
select divak.MENO,count(divak.MENO)
from sledovanost
natural join tv_stanice
natural join divak
group by divak.meno
order by count(divak.MENO)desc;
My query
You can achieve this by a having-clause, in which you compare each MENO count with the maximum MENO count (retrieved by a subquery):
select divak.MENO,count(divak.MENO)
from sledovanost
natural join tv_stanice
natural join divak
group by divak.meno
having count(divak.MENO) = (
select (max(count(divak.MENO))
from sledovanost
natural join tv_stanice
natural join divak
group by divak.meno)
BTW: I'd change the query to join .. ON .. syntax; natural join, which connects tables on equally named attributes, bears the danger of "unintended connections" whenever the db schema changes.
Don't use natural join. It uses the names of the columns to match tables, and doesn't show the names in the query. It is a bug waiting to happen. Use USING or ON.
In Oracle, you would normally do this using row_number() or rank() depending on whether or not you wanted duplicates:
with t as (<your query here but name the second column>)
select t.*
from (select t.*, rank() over (order by cnt desc) as seqnum
from t
) t
where seqnum = 1;

How to limit results of a correlated subquery that uses outer query aliases?

I'm struggling with a subquery (Oracle 11). Example below is 'invented' for the purpose of the question.
SELECT TM.TMID AS TEAM_ID
,(SELECT FIRST_NAME || ' ' || LAST_NAME
FROM PLAYER PL
WHERE PL.TMID=**TM.TMID**
ORDER BY AGE) AS OLDEST_PLAYER_NAME
FROM TEAM **TM**
Again, this is an invented example. Let's not get into any discussions about naming conventions, normalization or age calculations.
The issue at hand is that the correlated query returns multiple results and I need to pick the first one. If I wrap that correlated query inside another one to do a select .... where rownum<=1, I will break the alias reference.
Please work with my question!
When trying to help, please state how I can limit results of the subquery above or state that it cannot be done. Do not rewrite this query into some joins because I would not be able to validate that your solution works. If subquery above cannot be limited to a single row, I will evolve complete query into joins myself. This question is strictly about limiting results without breaking the alias reference.
Something like this may work. You don't need a correlated subquery, you need a join with a properly defined subquery.
Not tested since (well, you know the rest).
select tm.tmid as team_id, x.first_name || ' ' || x.last_name as oldest_player_name
from team tm
inner join
(select first_name, last_name, tmid,
row_number() over (partition by tmid order by age desc) as rn
from player) x
on tm.tmid = x.tmid
where rn = 1;
Edited: If you must use a correlated subquery for whatever reason, you can do it like so:
SELECT TM.TMID AS TEAM_ID
,(SELECT FIRST_NAME || ' ' || LAST_NAME
FROM
(select first_name, last_name, tmid,
row_number() over (partition by tmid order by age desc) rn
from PLAYER
) PL
WHERE PL.TMID=TM.TMID
AND rn = 1) AS OLDEST_PLAYER_NAME
FROM TEAM TM
The optimizer should be smart enough to see that the innermost subquery is constant (not correlated) and evaluate it only once.
The constraints on answering exclude joins and to continue with the correlated subquery in the select clause.
The options I can think of are
Use MAX() or MIN()
Use row_number () as shown elsewhere
Use an ORDER BY then: OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
E.g
( Select MAX(name) from tablex x
where x.id = outer.id )
for a limit of 1 you can do something like the following:
select
customer_id
, (select cust_last_name
from demo_customers c
where c.customer_id = o.customer_id
ORDER BY c.cust_state desc
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
) name
from demo_orders o
But: in that example there is simply no good reason not to use a join instead which would be far more efficient.
select
o.customer_id
, c.cust_last_name
from demo_orders o
inner join demo_customers c
on c.customer_id = o.customer_id

syntax error in Hive Query

I am trying to answer this question
Of the right-handed batters who were born in October and died in
2011, which one had the most hits in his career?
My attempt to get the query, Please ignore the total, it supposed to for sums for b.hits, dont know how to alias it.
SELECT n.id, n.bmonth, n.dyear,n.bats, SUM(b.hits) FROM master n
JOIN (SELECT b.id , b.hits FROM batting GROUP BY id) o
WHERE n.bmonth == 10 AND n.dyear == 2011) x
ON x.id=n.id
ORDER BY total DESC;
Incase anyone needs the schema of the two tables used, look below.
INSERT OVERWRITE DIRECTORY '/home/hduser/hivetest/answer4'
SELECT n.id, n.bmonth, n.dyear,n.bats, SUM(b.hits) FROM master n
JOIN (SELECT b.id , b.hits FROM batting GROUP BY id) o
WHERE n.bmonth == 10 AND n.dyear == 2011) x
ON x.id=n.id
ORDER BY total DESC;
First, although Hive accepts ==, that doesn't mean you should use it. The standard SQL equality operator is simply =. There is no reason to use a synonym.
I suspect the problem is several things:
The lack of group by.
Mis-use of aggregation functions.
Missing aliases
SQL query clauses in the correct order
Unbalanced parentheses
In other words, the query is just a mess. You need to review the basics of query syntax. Does this work?
SELECT m.id, m.bmonth, m.dyear, m.bats, b.hits as total
FROM master m JOIN
(SELECT b.id, SUM(b.hits) as hits
FROM batting b
GROUP BY id
) b
ON b.id = m.id
WHERE m.bmonth = 10 AND m.dyear = 2011
ORDER BY total DESC;

AS being ignored in a subquery

Still learning SQL here... I have part of a subquery:
(Select MAX(cost) AS Cost_of_Car FROM Car_Purchase)
But it does not take my label just uses the one from the table, in this case "cost"
Any ideas?
EDIT: Just realized I could in my SELECT statement call out AS "NAME OF COLUMN", but why does it not accept AS in the subquery?
POSTING FULL QUERY
SELECT CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description
FROM Car_Purchase
JOIN CAR ON Car_Purchase.purchase_id = CAR.purchase_id
GROUP BY CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description
HAVING Car_Purchase.cost = (SELECT MAX(cost) AS Cost_of_Car FROM Car_Purchase)
The AS keyword is not being ignored.
You're using subquery in where clause. Remember, where clause is used for filtering the query result, not for displaying the data.
If you want to see how AS work in subquery, try this:
SELECT CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description, Cost_of_Car
FROM Car_Purchase
JOIN CAR ON Car_Purchase.purchase_id = CAR.purchase_id
join (SELECT MAX(cost) AS Cost_of_Car FROM Car_Purchase) subquery
ON Car_Purchase.cost = subquery.Cost_of_Car
GROUP BY CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description
In this query, I put the subquery in from clause. So your query result now have Cost_of_Car column and you can display it in select clause.
In fact, since, as noted by others the Max(Cost) is not being used elsewhere in the query, you don't need to alias it at all. And since you don't have a aggregate function anywhere in the sql it does not need to be a group By query
Select cp.name, cp.Cost CostOfCar,
cp.cost_per_night, cp.description
From Car_Purchase cp Join Car c
On c.purchase_id = cp.purchase_id
Where cp.cost = (SELECT MAX(cost) FROM Car_Purchase)
Is sufficient and should work

Oracle SQL help

I posted on Friday (sql multiple count) and had a few responses.
Having tried to implement them today, I keep getting the same error.
My SQL code now is:
SELECT MBDDX_STUDY.STUDY_NAME,
COUNT(MBDDX_EXPERIMENT.STUDY_ID)
AS NUMBER_OF_EXPERIMENTS
FROM MBDDX_STUDY
INNER JOIN MBDDX_EXPERIMENT
ON MBDDX_STUDY.ID = MBDDX_EXPERIMENT.STUDY_ID
INNER JOIN (SELECT COUNT(MBDDX_TREATMENT_GROUP.GROUP_NO)
FROM MBDDX_TREATMENT_GROUP)
ON MBDDX_TREATMENT_GROUP.STUDY_ID = MBDDX_STUDY.ID
GROUP BY MBDDX_STUDY.STUDY_NAME
I keep getting the error:
ORA-00904: "MBDDX_TREATMENT_GROUP"."STUDY_ID": invalid identifier
Is it because it is outside of the inner join bracket, i.e. out of scope? I am very new to SQL and cannot understand why it wont work. I can get it working using select subqueries (without joins) but I want to also be able to work with joins.
If it matters any I am using Toad for Oracle.
Thanks.
Because you join with a query. Give a name to that query, and refer to it that way:
SELECT MBDDX_STUDY.STUDY_NAME
, COUNT ( MBDDX_EXPERIMENT.STUDY_ID )
AS NUMBER_OF_EXPERIMENTS
FROM MBDDX_STUDY
INNER JOIN MBDDX_EXPERIMENT
ON MBDDX_STUDY.ID = MBDDX_EXPERIMENT.STUDY_ID
inner JOIN ( SELECT study_id, COUNT ( MBDDX_TREATMENT_GROUP.GROUP_NO )
FROM MBDDX_TREATMENT_GROUP group by study_id ) AS my_query
ON my_query.STUDY_ID = MBDDX_STUDY.ID
GROUP BY MBDDX_STUDY.STUDY_NAME
For one thing, a subquery must have an alias. Change:
inner JOIN ( SELECT COUNT ( MBDDX_TREATMENT_GROUP.GROUP_NO )
FROM MBDDX_TREATMENT_GROUP )
ON MBDDX_TREATMENT_GROUP.STUDY_ID = MBDDX_STUDY.ID
to
inner JOIN ( SELECT COUNT ( MBDDX_TREATMENT_GROUP.GROUP_NO )
FROM MBDDX_TREATMENT_GROUP ) as CountAlias
ON MBDDX_TREATMENT_GROUP.STUDY_ID = MBDDX_STUDY.ID
The second thing is that you have to include all columns you plan to use. Right now, the subquery just selects a count, but the ON clause references STUDY_ID. You can fix that by including STUDY_ID in the subquery select list, like:
inner JOIN (
SELECT STUDY_ID
, COUNT(MBDDX_TREATMENT_GROUP.GROUP_NO) as GroupCount
FROM MBDDX_TREATMENT_GROUP) as CountAlias
ON MBDDX_TREATMENT_GROUP.STUDY_ID = MBDDX_STUDY.ID
Now after that, you might hit other issues, but I'm hoping this will get you started.