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
Related
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
I have a table with columns:
ID | FULLNAME | VALUE
01 Joseph 10
02 Sam 50
... ... ...
I need to select row with maximum value, and show info like
FULLNAME | VALUE
I tried using group function MAX(), but I can't select fullname, because if I use it as a GROUP BY expression, it will select max in groups.
Other way, is to use WITH statement, order table by value desc, use
rank() OVER (PARTITION BY ID) AS max_id
function and maximum value will be on max_id = 1, and then use
WHERE max_id = 1
to remove other rows.
But I think there is a way to do this better and I can't find one.
UPDATE:
A tricky solution to this problem is
SELECT *
FROM t t1
LEFT JOIN t t2 ON t1.value<t2.value
WHERE t2.value IS NULL
The simplest way is to sort the data and pull one row:
select t.*
from t
order by value desc
fetch first 1 row only;
If you want ties, you can add with ties to the fetch first.
Another method is:
select t.*
from t
where t.value = (select max(t2.value) from t t2);
This can have very good performance with an index on value.
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.
I want to make a select query which groups rows based on a given column and then sorts by size of such groups.
Let's say we have this sample data:
id type
1 c
2 b
3 b
4 a
5 c
6 b
I want to obtain the following by grouping and sorting the column 'type' in a descending way:
id type
2 b
3 b
6 b
1 c
5 c
4 a
As of now I am only able to get the count of each group but that is not exactly what I need:
SELECT *, COUNT(type) AS typecount
FROM sampletable
GROUP BY type
ORDER BY typecount DESC, type ASC
id type count
2 b 3
1 c 2
4 a 1
Can anybody please give me a hand with this query?
Edit:
Made 'b' the biggest group to avoid coming to the same solution by using only SORT BY
You can't use a column alias in your GROUP BY; just repeat the expression:
SELECT type, COUNT(type) AS count
FROM sampletable
GROUP BY type
ORDER BY COUNT(*) DESC, type ASC
Note that I changed the SELECT clause - you can't use * in your SELECT either since expressions in the SELECT need to either be in the GROUP BY clause or an aggregation.
It may not be the best way, but it will give you what you want.
You work out the totals for each group and then join that "virtual" table to your original table by the determined counts.
SELECT *
FROM sampletable s1
INNER JOIN (SELECT count(type) AS iCount,type
FROM sampletable
GROUP BY type) s2 ON s2.type = s1.type
ORDER BY s2.iCount DESC, s1.type ASC
http://sqlfiddle.com/#!9/f6b0c4/6/0
You can't perform GROUP BY operation on COLUMN ALIAS.
The reason why you can't use ALIAS on the GROUP BY clause that is created on the same level of the SELECT statement is because the GROUP BY is executed before the SELECT clause in which the ALIAS is created.
This is the SQL Order of Operation:
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
Try following query:
SELECT type, COUNT(type) AS count
FROM sampletable
GROUP BY type
ORDER BY COUNT(*) DESC, type ASC;
EDIT:-
SELECT id, type
FROM sampletable
ORDER BY type DESC, id ASC;
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