How to avoid duplicating statements with grouping functions? - sql

I have a t-sql query where sum function is duplicated.
How to avoid duplicating those statements?
select
Id,
sum(Value)
from
SomeTable
group by
Id
having
sum(Value) > 1000

It look like table aliasing is not supported.
I think with should work:
with tmptable (id,sumv)
as
(select
Id,
sum(Value) as sumv
from
SomeTable
group by
Id
)
select
id,
sumv
from
tmptable
where
sumv>1000
And a fiddle:
http://sqlfiddle.com/#!6/0d3f2/2

You need to remove the sum(Value) from the group by clause.

You can use GROUP BY 1, 2 to group by (in this case) the first and second columns, and thus avoid duplication in the GROUP BY clause.

Related

sql aggregations

any ideas why this doesn't work?
select [column_name_2], max(count(distinct([column_name_1])))
from [table_name]
group by [column_name_2]
but it works if done like this
select [column_name_2], count(distinct([column_name_1])) as [x]
into #temp_table
from [table_name]
group by [column_name_2]
select max(x)
from #temp_table
Well, that's just the way SQL (the language) is defined to work. When you use GROUP BY, the corresponding SELECT list will produce a row for each group in the result. You're trying to take that result and aggregate twice, once with GROUP BY [column_name_2] and a second time with GROUP BY (), as defined by standard SQL. We can't do that in the same query expression.
The good news is you can break this up into more than one query expression:
WITH cte1 AS (
SELECT count(distinct([column_name_1])) AS cnt
FROM [table_name]
GROUP BY [column_name_2]
)
SELECT MAX(cnt) FROM cte1
;
or use a derived table.
You can even order the initial query result by cnt DESC and limit the result to the first row.
In your case, you may not want just the MAX, but also the other column.
With SQL Server, which you may be using. Note: You should add a database specific tag to the question.
SELECT TOP 1 [column_name_2], count(distinct([column_name_1])) AS cnt
FROM [table_name]
GROUP BY [column_name_2]
ORDER BY cnt DESC
;
I don't understand "this doesn't work", what were you expecting and what did you get? Normally you include the GROUP BY value in the result set. So it would be:
select [column_name_2], max(cnt) cnt
from (select [column_name_2], count(distinct [column_name_1]) cnt
from [table_name]
group by [column_name_2]) x
group by [column_name_2]
Ok, after reading your comment I think above is what you are looking for.
SELECT [column_name_two]
, max(x) x
FROM (
SELECT [column_name_two]
, COUNT(DISTINCT [column_name_one]
FROM table_name
GROUP BY [column_name_two]
) AS Tbl
GROUP BY [column_name_two]

best way to get count and distinct count of rows in single query

What is the best way to get count of rows and distinct rows in a single query?
To get distinct count we can use subquery like this:
select count(*) from
(
select distinct * from table
)
I have 15+ columns and have many duplicates rows as well and I want to calculate count of rows as well as distinct count of rows in one query.
More if I use this
select count(*) as Rowcount , count(distinct *) as DistinctCount from table
This will not give accurate results as count(distinct *) doesn't work.
Why don't you just put the subquery inside another query?
select count(*),
(select count(*) from (select distinct * from table))
from table;
create table tbl
(
col int
);
insert into tbl values(1),(2),(1),(3);
select count(*) as distinct_count, sum(sum) as all_count
from (
select count(col) sum from tbl group by col
)A
I think I have understood what you are looking for. You need to use some window function. So, you query should be look like =>
Select COUNT(*) OVER() YourRowcount ,
COUNT(*) OVER(Partition BY YourColumnofGroup) YourDistinctCount --Basic of the distinct count
FROM Yourtable
NEW Update
select top 1
COUNT(*) OVER() YourRowcount,
DENSE_RANK() OVER(ORDER BY YourColumn) YourDistinctCount
FROM Yourtable ORDER BY TT DESC
Note: This code is written sql server. Please check the code and let me know.

How to use to functions - MAX(smthng) and after COUNT(MAX(smthng)

I don't understand why I can't use this in my code :
SELECT MAX(SMTHNG), COUNT(MAX(SMTHNG))
FROM SomeTable;
Searched for an answer but didn't find it in documentation about these aggregate functions.
Also I get an SQL-compiler error "Invalid column name "SMTHNG"".
You want to know what the maximum SMTHNG in the table is with:
SELECT MAX(SMTHNG) FROM SomeTable;
This is an aggregation without GROUP BY and hence results in one single row containing the maximum SMTHNG.
Now you also want to know how often this SMTHNG occurs and you add COUNT(MAX(SMTHNG)). This, however, does not work, because you can not aggregate an aggregate directly.
This doesn't work either:
SELECT ANY_VALUE(max_smthng), COUNT(*)
FROM (SELECT MAX(smthng) AS max_smthng FROM sometable) t;
because the sub query only contains one row, so it's too late to count.
So, either use a sub query and select from the table again:
SELECT ANY_VALUE(smthng), COUNT(*)
FROM sometable
WHERE smthng = (SELECT MAX(smthng) FROM sometable);
Or count per SMTHNG before looking for the maximum. Here is how to get the counts:
SELECT smthng, COUNT(*)
FROM sometable
GROUP BY smthng;
And the easiest way to get the maximum from this result is:
SELECT TOP(1) smthng, COUNT(*)
FROM sometable
GROUP BY smthng
ORDER BY COUNT(*) DESC;
First of all, please read my comment.
Depending on what you're trying to achieve, the statement have to be changed.
If you want to count the highest values in SMTHNG field, you may try this:
SELECT T1.SMTHNG, COUNT(T1.SMTHNG)
FROM SomeTable T1 INNER JOIN
(
SELECT MAX(SMTHNG) AS A
FROM SomeTable
) T2 ON T1.SMTHNG = T2.A
GROUP BY T1.SMTHNG;
use cte like below or subquery
with cte as
(
select count(*) as cnt ,col from table_name
group by col
) select max(cnt) from cte
you can not use double aggregate function at a time on same column

count all the distinct records in a table

I need to count all the distinct records in a table name with a single query and also without using any sub-query.
My code is
select count ( distinct *) from table_name
It gives an error:
Incorrect syntax near '*'.
I am using Microsoft SQL Server
Try this -
SELECT COUNT(*)
FROM
(SELECT DISTINCT * FROM [table_name]) A
I'm afraid that if you don't want to use a subquery, the only way to achieve that is replacing * with a concatenation of the columns in your table
select count(distinct concat(column1, column2, ..., columnN))
from table_name
To avoid undesired behaviours (like the concatenation of 1 and 31 becoming equal to the concatenation of 13 and 1) you could add a reasonable separator
select count(distinct concat(column1, '$%&£', column2, '$%&£', ..., '$%&£', columnN)
from table_name
You can use CTE.
;WITH CTE AS
(
SELECT DISTINCT * FROM TableName
)
SELECT COUNT(*)
FROM CTE
Hope this query gives you what you required.
As others mentioned, you cannot use DISTINCT with *. Also it is good practice to use a column name instead of the *, like a unique key / primary key of the table.
SELECT COUNT( DISTINCT id )
FROM table
select distinct Name , count(Name) from TableName
group by Name
having count(Name)=1
select ##rowcount
I had the same issue involving a query that had multiple joins to tables and I could not simply do count(distinct ) or count(distinct alias.).
My solution was to create a string made up of the key columns I cared about and count them.
SELECT Count(DISTINCT person.first || '~' || person.last)
from person;
If you want to use DISTINCT keyword, you need to specify column name on which bases you want to get distinct records.
Example:
SELECT count(DISTINCT Column-Name) FROM table_name

case in group by in a store procedure

is possible do a case in a group by?
similar to this:
select * from table
GROUP BY
CASE WHEN #Attivita=0 THEN (RANK() OVER (GROUP BY Nome,AccountID,Matricola DESC))
END
thanks
you have to group by all selected (non-aggregated) columns..
so if you select * you will need to group by all of them ...
If instead of group by you mean order by then yes you can..
No: this would make no sense.
You can't
use GROUP BY and SELECT *
use RANK in a subclause
use GROUP BY in the OVER clause
GROUP BY over a ranking function makes no sense
What are you trying to do, with input/output and schema please.
Edit, based on gaby's answer
select
*
from
(
SELECT
*, RANK() OVER (GROUP BY Nome,AccountID,Matricola DESC) as bar
from
table
) foo
ORDER BY
CASE WHEN #Attivita=0 THEN bar END