group by oracle - sql

I have a table as below:
id value
-------------------------
1 1
5 1
7 1
8 4
I can't get to table as below:
id value
-------------------------
1 1
8 4
The SQL is
select id,value from table_1 group by id_a

All you have here is a simple MIN() aggregate.
SELECT MIN(id), value AS id FROM table_1 GROUP BY value

Try this:
select min(id), id_a from table_1 group by id_a

SELECT T.value,MIN(id) AS MIN_ID
FROM TABLE T
GROUP BY T.value;

In order to use a group by expression, you must have one or more aggregating functions: count, min, max, sum, avg etc. These functions operate on a group of rows at a time. Now when you use an aggregate function with a none aggregated column(s) you need to use the group by clause.
The below will give you the correct answer:
select min(id) id, value from table_1 group by value

Related

COUNT of GROUP of two fields in SQL Query -- Postgres

I have a table in postgres with 2 fields: they are columns of ids of users who have looked at some data, under two conditions:
viewee viewer
------ ------
93024 66994
93156 93151
93163 113671
137340 93161
92992 93161
93161 93135
93156 93024
And I want to group them by both viewee and viewer field, and count the number of occurrences, and return that count
from high to low:
id count
------ -----
93161 3
93156 2
93024 2
137340 1
66994 1
92992 1
93135 1
93151 1
93163 1
I have been running two queries, one for each column, and then combining the results in my JavaScript application code. My query for one field is...
SELECT "viewer",
COUNT("viewer")
FROM "public"."friend_currentfriend"
GROUP BY "viewer"
ORDER BY count DESC;
How would I rewrite this query to handle both fields at once?
You can combine to columns from the table into a single one by using union all then use group by as below:
select id ,count(*) Count from (
select viewee id from vv
union all
select viewer id from vv) t
group by id
order by count(*) desc
Results:
This is a good place to use a lateral join:
select v.viewx, count(*)
from t cross join lateral
(values (t.viewee), (t.viewer)) v(viewx)
group by v.viewx
order by count(*) desc;
You can try this :
SELECT a.ID,
SUM(a.Total) as Total
FROM (SELECT t.Viewee AS ID,
COUNT(t.Viewee) AS Total
FROM #Temp t
GROUP BY t.Viewee
UNION
SELECT t.Viewer AS ID,
COUNT(t.Viewer) AS Total
FROM #Temp t
GROUP BY t.Viewer
) a
GROUP BY a.ID
ORDER BY SUM(a.Total) DESC

Oracle SQL how to find count less than avg

my code is like :
SELECT
number,
name,
count(*) as "the number of correct answer"
FROM
table1 NATURAL JOIN table2
WHERE
answer = 'T'
GROUP BY
number,
name
HAVING
count(*) < avg(count(*))
ORDER BY
count(*);
Here I want to find the group with count less than the average number of count for each group, but here I failed to use HAVING or WHERE, could anyone help me?
How can I only select the 1 name1 2 since avg of count is (2+6+7)/3 = 5 and only 2 is less than avg.
number name count
1 name1 2
2 name2 6
3 name3 7
I would advise you to never use natural joins. They obfuscate the query and make the query a maintenance nightmore.
You can use window functions:
SELECT t.*
FROM (SELECT number, name,
COUNT(*) as num_correct,
AVG(COUNT(*)) OVER () as avg_num_correct
FROM table1 JOIN
table2
USING (?). -- be explicit about the column name
WHERE answer = 'T'
GROUP BY number, name
) t
WHERE num_correct < avg_num_correct;
As with your version of the query, this filters out all groups that have no correct answers.
I would place your current query logic into a CTE, and then tag on the average count in the process:
WITH cte AS (
SELECT number, name, COUNT(*) AS cnt,
AVG(COUNT(*)) OVER () AS avg_cnt
FROM table1
NATURAL JOIN table2
WHERE answer = 'T'
GROUP BY number, name
)
SELECT number, name, cnt AS count
FROM cte
WHERE cnt < avg_cnt;
Here we are using the AVG() function as an analytic function, with the window being the entire aggregated table. This means it will find the average of the counts per group, across all groups (after aggregation). Window functions (almost) always evaluate last.

Find unique row when two rows when two row have the column id as the same, but have other column a date which I want the newset one

Create a query of unique values, but some of them have same ids but different dates. Just want the newest date. I am joining several tables, but do not know how to handle this
SELECT DISTINCT ap.id, MAX(ap.date)
FROM sometable;
I tried this code but no result.
I get these resulst:
id date
------------
1 10/31/18
1 10/15/18
2 11/05/17
2 11/04/17
But I want these results:
1 10/31/18
2 11/05/17
In case your query has other columns too that you want to show in result, you will have to resort to analytical function, in such case your query will look like following
select id, the_date /* ,other columns */ from (
select row_number() over (partition by id
order by some_date /* your date column */ desc ) ord,
id,
some_date the_date
/* ,other columns */
from <your_table>
) where ord = 1
;
You need group by
SELECT ap.id, MAX(ap.date)
from sometable ap
group by ap.id;
the aggregation function as min(), max() ,, count() need group by for return the related agreagated result
and for the query in you comment you should use
SELECT ap.id, MAX(ap.date)
from sometable ap
where ap.id in ( id1, id2, id3.... idns)
group by ap.id

PostgreSQL using sum in where clause

I have a table which has a numeric column named 'capacity'. I want to select first rows which the total sum of their capacity is no greater than X, Sth like this query
select * from table where sum(capacity )<X
But I know I can not use aggregation functions in where part.So what other ways exists for this problem?
Here is some sample data
id| capacity
1 | 12
2 | 13.5
3 | 15
I want to list rows which their sum is less than 26 with the order of id, so a query like this
select * from table where sum(capacity )<26 order by id
and it must give me
id| capacity
1 | 12
2 | 13.5
because 12+13.5<26
A bit late to the party, but for future reference, the following should work for a similar problem as the OP's:
SELECT id, sum(capacity)
FROM table
GROUP BY id
HAVING sum(capacity) < 26
ORDER by id ASC;
Use the PostgreSQL docs for reference to aggregate functions: https://www.postgresql.org/docs/9.1/tutorial-agg.html
Use Having clause
select * from table order by id having sum(capacity)<X
You can use the window variant of sum to produce a cumulative sum, and then use it in the where clause. Note that window functions can't be placed directly in the where clause, so you'd need a subquery:
SELECT id, capacity
FROM (SELECT id, capacity, SUM(capacity) OVER (ORDER BY id ASC) AS cum_sum
FROM mytable) t
WHERE cum_sum < 26
ORDER BY id ASC;

Using output of function from select in where clause

What is the correct way to write an SQL Query so I can use the output of a function that I have used in the Select Statement in the Where clause?
Data Table:
ID Count_ID
111 2
111 2
222 3
222 3
222 3
333 1
Query:
Select ID, Count(Table1.ID) As Count_ID
From Table1
Where Count_ID = 3
Group By ID
It gives me invalid column name currently in there Where Clause for Count_ID.
There's a circular dependency on your filtering. You want to only select records where the count is 3, but you must count them before you can determine this. This means that you need a HAVING clause rather than a WHERE clause (to filter on an aggregate function, you always need a HAVING clause).
Furthermore, you can't use an aliased column name for an aggregate function in a WHERE or HAVING clause. You have to repeat the function in the filtering:
Select ID, Count(ID) As Count_ID
From Table1
Group By ID
HAVING Count(ID) = 3;
In this case, because you're referencing an aggregate function and a grouping, you have to use a HAVING clause.
Select ID, Count(Table1.ID) As Count_ID
From Table1
Group By ID
Having Count(Table1.ID) = 3
Alternatively you can use this too:
SELECT ID, Count_ID
FROM
(SELECT ID, Count(ID) AS Count_ID
FROM Table1
GROUP BY ID) Calced
WHERE Calced.Count_ID = 3;
http://sqlfiddle.com/#!4/f2a73/5