Group function is not allowed here - sql

When I run the following query, I get
ORA-00934: group function is not allowed here
what is the problem ?
select c.Numcom,c.Nompr,c.salaire_fix
from commercialv c,comercialv c1
where c.salaire_fix=(max(c1.salaire_fix) );

You cannot use an aggregate function in a WHERE clause.
Given your use case, you probably want a subquery:
select c.Numcom,c.Nompr,c.salaire_fix
from commercialv c
where c.salaire_fix=(select max(salaire_fix) from comercialv);
The rational is that aggregate functions works on a set. The WHERE clause on the other hand, has only access to the data of one row.

You can do what you want with analytic functions:
select Numcom, Nompr, salair_fix
from (select c.Numcom, c.Nompr, c.salaire_fix,
max(c.salaire_fix) over () as maxs
from commercialv c
) c
where c.salaire_fix = c.maxs;
As for your query, aggregation functions are not permitted in the where clause.

You could also do this query using MAX() as a window function (or analytic function if you prefer the Oracle lingo):
SELECT numcom, nompr, salaire_fix FROM (
SELECT numcom, nompr, salaire_fix, MAX(salaire_fix) OVER ( ) AS max_salaire_fix
FROM commercialv
) WHERE salaire_fix = max_salaire_fix;
You could also use RANK():
SELECT numcom, nompr, salaire_fix FROM (
SELECT numcom, nompr, salaire_fix, RANK() OVER ( ORDER BY salaire_fix DESC ) AS salaire_fix_rank
FROM commercialv
) WHERE salaire_fix_rank = 1;
Or even ROWNUM:
SELECT * FROM (
SELECT numcom, nompr, salaire_fix
FROM commercialv
ORDER BY salaire_fix DESC
) WHERE rownum = 1;
The only difficulty with the last is that it will get only one row even if there are additional rows with the maximum value of salaire_fix. The first two queries will get more than one row in that case.

You can't use group function in where clause so you can use having clause. Example:
SELECT DEPTNO,COUNT(*)
FROM EMP
GROUP BY DEPTNO
HAVING COUNT(*) >= 2;

Related

How to replace IN CLAUSE USING EXISTS?

select
TV.ATTRIBUTE
FROM
TABLE_VALUE TV
WHERE
TV.NUMBERS IN (SELECT MAX(TV1.NUMBERS) FROM TABLE_VALUE TV1
WHERE TV.UNIQUE_ID=TV1.UNIQUE_ID GROUP BY UNIQUE_ID )
I'm not sure exists would help here, because - as you put it - for each unique_id there be many numbers values, and you want to select attribute for highest numbers for that particular unique_id.
exists is useful when you want to check whether something ... well, exists, but that's not the case here.
You do not want EXISTS, instead you can use the RANK or DENSE_RANK analytic functions:
SELECT attribute
FROM (
SELECT attribute,
DENSE_RANK() OVER (PARTITION BY unique_id ORDER BY numbers DESC) AS rnk
FROM table_value
)
WHERE rnk = 1
or use the MAX analytic function:
SELECT attribute
FROM (
SELECT attribute,
numbers,
MAX(numbers) OVER (PARTITION BY unique_id) AS max_numbers
FROM table_value
)
WHERE numbers = max_numbers;
Either option will only read from the table once.
If you really did want to use EXISTS (or IN) then it will be less efficient as you will query the same table twice but you can do it with a HAVING clause:
SELECT tv.attribute
FROM table_value tv
WHERE EXISTS(
SELECT 1
FROM table_value tv1
WHERE tv1.unique_id = tv.unique_id
HAVING MAX(tv1.numbers) = tv.numbers
)
fiddle

Rank Function inside case statement

I am trying to use Rank Function inside a case statement and give where rank_number = 1 , it's throwing error as unexpected where Condition. Can some one help me how to assign rank in where clause inside case statement
You can't use the RANK() analytic function (or any other one, for that matter) in the WHERE clause of a query. The results of the rank computation are not yet available. But they are available in the SELECT clause or the ORDER BY clause. One workaround would be to subquery:
SELECT *
FROM
(
SELECT t.*, RANK() OVER (ORDER BY blah) rnk
FROM yourTable t
) s
WHERE rnk = 1;
Some databases support a QUALIFY clause, where it is possible to use analytic functions. Assuming you are using something like Teradata or BigQuery, you could use:
SELECT *
FROM yourTable
WHERE 1 = 1
QUALIFY RANK() OVER (ORDER BY blah) = 1;

MAX and COUNT function doesn't work together

I want to count id_r and then return the maxim value of count using
MAX(COUNT(id_r))
but shows me this error
the error
Thanks :)
You can only use one aggregation function at a time.
The ANSI standard way to do what you want is:
select count(*)
from t
group by ?
order by count(*) desc
fetch first 1 row only;
Or alternatively a subquery:
select max(cnt)
from (select count(*) as cnt
from t
group by ?
) x;
Note that you want a group by of something, perhaps id_r.
Try this:
SELECT MAX(e1) as Expr1 FROM (
SELECT COUNT(id_r) as e1
FROM Angajat) as t1
COUNT(id_r) wil return only 1 result since there is no group by clause. Hence, there is no use of max.
You need to add a group by clause in subquery:
SELECT MAX(e1) as Expr1 FROM (
SELECT column1, COUNT(id_r) as e1
FROM Angajat
GROUP BY column1
) as t1

Printing same rows twice in SQL Server

I'm using this query
SELECT
[SCORECARD_NAME], [SCORE_NAME],
[TOTAL_ROWS], [VALID_PERCENTAGE], [INVALID_ROWS]
FROM
{table_name}
and I'm getting the result twice. I'm not getting why its happening like that
what is the solution for this?
You can use SELECT DISTINCT, or here is an option using a CTE with a window function:
;WITH CTE AS (
SELECT [SCORECARD_NAME], [SCORE_NAME], [TOTAL_ROWS], [VALID_PERCENTAGE],[INVALID_ROWS],
ROW_NUMBER() OVER (PARTITION BY [SCORECARD_NAME]
ORDER BY [SCORECARD_NAME]) AS DuplicateCount
FROM Table_Name
)
SELECT * FROM CTE WHERE DuplicateCount = 1;
In case you want rows with same entries to be displayed once then use distinct:
SELECT DISTINCT
[SCORECARD_NAME], [SCORE_NAME], [TOTAL_ROWS],
[VALID_PERCENTAGE], [INVALID_ROWS]
FROM
{table_name};
Let me know in case of any queries.

Optimize sql query with the rank function

This query gets the top item in each group using the ranking function.
I want to reduce the number of inner selects down to two instead of three. I tried using the rank() function in the innermost query, but couldn't get it working along with an aggregate function. Then I couldn't use a where clause on 'itemrank' without wrapping it in yet another select statement.
Any ideas?
select *
from (
select
tmp.*,
rank() over (partition by tmp.slot order by slot, itemcount desc) as itemrank
from (
select
i.name,
i.icon,
ci.slot,
count(i.itemid) as itemcount
from items i
inner join citems ci on ci.itemid = i.itemid
group by i.name, i.icon, ci.slot
) as tmp
) as popularitems
where itemrank = 1
EDIT: using sql server 2008
In Oracle and Teradata (and perhaps others too), you can use QUALIFY itemrank = 1 to get rid of the outer select. This is not part of the ANSI standard.
You can use Common Table Expressions in Oracle or in SQL Server.
Here is the syntax:
WITH expression_name [ ( column_name [,...n] ) ]
AS
( CTE_query_definition )
The list of column names is optional only if distinct names for all resulting columns are supplied in the query definition.
The statement to run the CTE is:
SELECT <column_list>
FROM expression_name;