I have column zone_dist in my table parcel16 that contains land use codes (character). My objective is to create a two-column table which in the left-hand column shows all of the distinct values and in the right shows the total count of those values in the table, in descending order. I have tried with a basic query but cannot apply the sum function to a character value:
SELECT zone_dist, SUM(zone_dist) AS quantity
FROM parcel16
GROUP BY zone_dist
returns the error:
ERROR: function sum(character varying) does not exist
LINE 1: SELECT zone_dist, SUM(zone_dist) AS quantity
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
How would one go about taking the counts of all distinct character values?
You want Count() rather than Sum(). Sum() adds the aggregate values (assumes int) whereas Count() will count the number of those values in which you group on.
SELECT zone_dist, count(zone_dist) AS quantity
FROM parcel16
GROUP BY zone_dist
order by count(zone_dist) desc
Sum does math on string data.
Count simply increments by 1 for each occurrence of a zone_dist. (thus it ignores nulls)
SELECT zone_dist, count(zone_dist) AS quantity
FROM parcel16
GROUP BY zone_dist
If we have NULL values in column zone_dist, count(zone_dist) won't count them and instead return 0
The quantity alias can be used in the order by clause
select zone_dist, count(*) as quantity
from parcel16
group by zone_dist
order by quantity desc
Related
I have data with two rows as follows:
group_id item_no
weoifne 1
weoifne 2
I want to retrieve the max item_no for each group_id. I'm using this query:
SELECT MAX(item_no)
OVER (PARTITION BY group_id)
FROM my_table;
I need only one record because I'm embedding this query in a CASE WHEN statement to apply logic based on whether or not item_no is the highest value per group.
Desired Output:
2
Actual Output:
2
2
How do I modify my query to only output one record with the maximum item_no per group_id?
Use an aggregate function along with GROUP BY instead of an window function.
A window function, also known as an analytic function, computes values over a group of rows and returns a single result for each row. This is different from an aggregate function, which returns a single result for a group of rows.
https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
SELECT group_id, MAX(item_no)
FROM my_table
GROUP BY group_id;
If you still want to use the window function, you can use DISTINCT in your script to get rid of the duplicates as shown below. DISTINCT works across all the columns
SELECT DISTINCT group_id
, MAX(item_no) OVER (PARTITION BY group_id)
FROM my_table
this is my database
CREATE TABLE korisnici(
name VARCHAR(30) NOT NULL,
amount DECIMAL(65,2)
);
INSERT INTO korisnici VALUES
("Marina",20.10),
("Petar",300.50),
("Ivana",100.70),
("Tomislav",50.20),
("Ivana",80.60),
("Petar",10.40),
("Marina",80.50),
("Ivana",70.50),
("Marina",130.20),
("Robert",60.20),
("Blanka",130.20),
("Blanka",220.40),
("Tomislav",150.20);
I would like to fetch all names from list which has average ammount of all their amounts greater than 150. Something like I tried
SELECT name, AVG(amount) AS avg FROM `korisnici` WHERE avg > 150 GROUP BY name
However my query fails, with error "Unknown column 'avg' in 'where clause'". Can someone give me a hint.
You can't use a column alias in a WHERE, JOIN, or HAVING clause, so you need to repeat the expression, but that's not the only problem. When filtering on the result of an aggregation, the HAVING clause should be used instead of WHERE:
SELECT name, AVG(amount) AS avg
FROM `korisnici`
GROUP BY name
HAVING AVG(amount) > 150
The reason is that the WHERE clause is applied before the grouping and aggregation (and is used to determine which records get grouped and aggregated), while HAVING is applied after the aggregation.
You can not write like that: it is a common SQL error.
avg is the identifier and you can not use an identifier in the where clause..
SELECT name, AVG(amount) AS avg
FROM `korisnici`
WHERE AVG(amount) > 150 GROUP BY name;
There you go..
I have a table with several columns. I want to query the account numbers in column Acct_Num that have three or more (>3) records in column R_CDE, how do I go about that?
I tried that but it gives me this error:
Msg 8120, Level 16
Column 'table.dbo.0813.RECORD_TYPE' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Any ideas?
You have three options:
Wrap RECORD_TYPE with an aggregate function
Add RECORD_TYPE to the GROUP BY clause
Remove RECORD_TYPE from the SELECT statement
What the error is essentially saying is that you haven't specified what RECORD_TYPE you want to display on the rows which are grouped by Acct_Num?
Any columns in the select statement either have to be present in your GROUP BY clause or be "wrapped" in an aggregate function:
SELECT
Acct_Num, -- no aggregate function since in GROUP BY clause
max(dbo.0813.RECORD_TYPE) -- aggregate function required
FROM ...
GROUP BY Acct_Num
SELECT
Acct_Num,
dbo.0813.RECORD_TYPE -- error: Msg 8120, Level 16 Column 'table.dbo.0813.RECORD_TYPE' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
FROM ...
GROUP BY Acct_Num
If the RECORD_TYPE will always be the same for a single Acct_Num then MIN() or MAX() would be fine.
DECLARE #tablo TABLE (oran INT,deger INT)
INSERT INTO #tablo
SELECT 10,NULL
UNION ALL
SELECT 10,20
SELECT oran*deger/100 FROM #tablo
SELECT SUM(oran*deger/100) FROM #tablo
SELECT NULL+2
When i use sum function it returns a value but if a column has a null value , i want it to return null.
How is it possible?
Thanks in advance...
sum() (as with the other aggregation functions) ignores NULLs when combining values from different rows. You can do what you want with additional logic:
SELECT (case when count(*) = count(oran*deger)
then SUM(oran*deger/100)
end)
FROM #tablo;
The construct count(*) = count(<whatever>) is the shortest way I can think of to determine if a value is NULL. The first part counts the number of rows in the group. The second counts the number of non-NULL values. If these are different, then there is a NULL value somewhere.
I have a column of count and want to divide the column by max of this column to get the rate.
I tried
select t.count/max(t.count)
from table t
group by t.count
but failed.
I also tried the one without GROUP BY, still failed.
Order the count desc and pick the first one as dividend didn't work in my case. Consider I have different counts for product subcategory. For each product category, I want to divide the count of subcategory by the max of count in that category. I can't think of a way avoiding aggregate func.
If you want the MAX() per category you need a correlated subquery:
select t.count*1.0/(SELECT max(t.count)
FROM table a
WHERE t.category = a.category)
from table t
Or you need to PARTITION BY your MAX()
select t.count/(max(t.count) over (PARTITION BY category))
from table t
group by t.count
The following works in all dialects of SQL:
select t.count/(select max(t.count) from t)
from table t
group by t.count;
Note that some versions of SQL do integer division, so the result will be either 0 or 1. You can fix this by multiplying by 1.0 or casting to a float.
Most versions of SQL also support:
select t.count/(max(t.count) over ())
from table t
group by t.count;
The same caveat applies about integer division.
You might want to try using a subquery to derive the max value (including both in the same query might not work the way that you are expecting, since you are grouping on the same column that you are aggregating)
Select t.count / (select max(sub.count) from table sub)
from table t
group by t.count