Error : aggregate may not appear in the WHERE clause - sql

I'm trying to get the max of column:
select * from
( select col1, count(*) as cnt from talbe1
group by col1
) dt
where cnt = max(cnt)
I tried to get exact value and it worked such as:
where cnt = 5
or
where cnt > 3
that was OK so what is wrong with the first query?
Edit: the numbers I put there (5, 3) are completely random, I want to get the maximum number of cnt.

Aggregate clauses have to go in the HAVING section. However, this won't work with your query as is. What you probably wanted to do was:
select top 1 col1, count(*) as cnt
from talbe1
group by col1
order by count(*) desc

You can do this with HAVING clause. For example if you want to get cnt=3 records
Select col1, count(*) as cnt from talbe1
Group by col1
Having count(*)=3
If you want to get MAX(cnt)
Select Top(1) col1, count(*) as cnt from talbe1
Group by col1
Order by cnt desc

I found a solution,
it was pretty simple:(I should have focused more)
select max(cnt) from
( select Fld301, count(*) as cnt from TbC3
group by Fld301
) dt

How about this query:
select * from
(
select
col1,
count(*) as cnt,
RANK() OVER(ORDER BY count(*) DESC) AS ran
from talbe1
group by col1
) dt
where ran=1

Related

Select duplicated data from table

Query
select * from table1
where having count(reference)>1
I want to select * the data which have duplicate data,any idea why my query is not working?
Below are my expect result..
You can make use of window function count to find number of rows per id and reference and then filter to get those which have count more than 1.
;with cte as (
select t.*, count(*) over (partition by id, reference) cnt
from table1 t
)
select * from cte where cnt > 1;
Demo
In the above solution, I have made an assumption that name and id has one to one correspondence (which is true as per your given data). If that's not the case, add name too in the partition by clause:
;with cte as (
select t.*, count(*) over (partition by name, id, reference) cnt
from table1 t
)
select * from cte where cnt > 1;
I might actually approach this by using a subquery with GROUP BY:
SELECT t1.*
FROM table1 t1
INNER JOIN
(
SELECT Name, ID, reference
FROM table1
GROUP BY Name, ID, reference
HAVING COUNT(*) > 1
) t2
ON t1.Name = t2.Name AND
t1.ID = t2.ID AND
t1.reference = t2.reference
Demo here:
Rextester
Try this ), first i get count by partition, after that i get row with count > 1
select No, Name, ID, Reference
from (select count(*) over (partition by name, ID, reference) cnt, table1.* from table1)
where cnt>1
The easy way (although maybe not the best for performance) would be:
select * from table1 where reference in (
select reference from table1 group by reference having count(*)>1
)
In a subselect you have the duplicated data, and in the outter select you have all the data for these references.

Getting only unique values in postresql

I need something like:
SELECT * FROM TABLE WHERE <value in column1 is always unique
(if ever any value will be noticed more than once, then skip this row)>
in postgresql.
So if I have these rows in table:
1;"something";"xoxox"
2;"other";"xoxox"
3;"something";"blablabla"
And then go with the query, then that should be result:
2;"other";"xoxox"
Any ideas?
Use count(*) as a window function:
select t.*
from (select t.*, count(*) over (partition by col1) as cnt
from t
) t
where cnt = 1;
Alternatively, you can use not exists and the id column:
select t.*
from t
where not exists (select 1 from t t2 where t2.col1 = t.col1 and t2.id <> t.id);
You can filter over count without the need of a subquery:
SELECT t.col1
FROM t
GROUP BY col1
HAVING COUNT(*) = 1
Other columns can be added by using an aggregation function like max, since there will only be 1 row per value:
SELECT t.col1, max(t.col2), max(t.col3)
FROM t
GROUP BY col1
HAVING COUNT(*) = 1

Group by and Count to select repeated rows

I wrote this query but it does not work as I expected.
1st Goal: select rows that have repeated in certain columns and return whole columns.
2nd Goal: Update a flag (a column) to identify which records have repeated.
Could you please help me?
SELECT
*
FROM AvvalV2NS AS M
WHERE EXISTS
(SELECT
M.Astate,
M.Acity,
M.Azone,
M.Abvillage,
M.Avillage,
COUNT(*)
FROM AvvalV2NS AS M
GROUP BY M.Astate,
M.Acity,
M.Azone,
M.Abvillage,
M.Avillage
HAVING COUNT(*) > 1)
If you want to get the rows that are duplicated, window functions are probably the easiest way:
select a.*
from (select a.*,
count(*) over (partition by M.Astate, M.Acity, M.Azone, M.Abvillage, M.Avillage) as cnt
from AvvalV2NS a
) a
where cnt > 1;
You can update a flag by doing something like this:
with toupdate as (
select a.*
from (select a.*,
count(*) over (partition by M.Astate, M.Acity, M.Azone, M.Abvillage, M.Avillage) as cnt
from AvvalV2NS a
) a
)
update toupdate
set isduplicate = (case when cnt > 1 then 1 else 0 end);
Suppose your table have an id column:
SELECT * FROM THE_TABLE WHERE ID IN (
SELECT ID FROM
(SELECT ID, REPEATING_COLUMNS, COUNT(*) FROM THE_TABLE GROUP BY REPEATING_COLUMNS HAVING COUNT(*) > 1)
)
UPDATE THE_TABLE SET THE_FLAG = "HERE WE GO" WHERE ID IN (
SELECT ID FROM
(SELECT ID, REPEATING_COLUMNS, COUNT(*) FROM THE_TABLE GROUP BY REPEATING_COLUMNS HAVING COUNT(*) > 1)
)
Hope this helps.

How to group rows, select one by a number - ext with other columns - in SQL Oracle?

I had an issue with writing a query that would gather groups in a column, and then select one of them by a number.
A good person (#sstan) gave me this:
select your_col
from (select your_col,
row_number() over (order by your_col) as rn
from your_table
group by your_col)
where rn = 2
And it works. However, it appears that my query needs to consider other columns. For now, it looks like this:
select MAINCOL, sum(some_col+other_col) as together_col, count(another_col)
from my_table
where date_col >= next_day(trunc(sysdate), 'MONDAY') - 14
and date_col < next_day(trunc(sysdate), 'MONDAY') - 7
group by MAINCOL, other_col, together_col
order by MAINCOL
So the challenge is to extend the upper query with what is below. Although I couldn't make it work, it seems simple..
You may try with Inner table alias
SELECT your_col,rn.your_col,rn.your_col2,rn.your_col3
FROM(select your_col,your_col2,your_col3,row_number() over (order by your_col)
from your_table group by your_col)as rn where rn = 2
Got it!
With help of Stack, of course.
select t.*
from (select MAINCOL, col1, col2, col3, col4, DENSE_RANK()OVER(ORDER BY MAINCOL) GROUPID
from tab_1
group by MAINCOL, col1, col2
) t
where GROUPID = 1;

Alternative for count distinct

I want an alternative way to write the following query
SELECT COUNT(DISTINCT col1) FROM table.
I dont want to use distinct. Is there an alternative way?
Try GROUP BY as a subquery and COUNT() from outside query. It would achieve same result.
SELECT COUNT(*)
FROM
(
SELECT Col1
FROM Table
GROUP BY Col1
) tbl
Select count(col1) from table GROUP BY col1
Try this
SELECT COUNT(Col1)
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY Col1 ORDER BY Col1) As RNO, Col1
FROM Table_Name)
WHERE RNO = 1