Can I Select DISTINCT on 2 columns and Sum grouped by 1 column in one query? - sql

Is it possible to write one query, where I would group by 2 columns in a table to get the count of total members plus get a sum of one column in that same table, but grouped by one column?
For example, the data looks like this
I want to get a count on distinct combinations of columns "OHID" and "MemID" and get the SUM of the "Amount" column grouped by OHID. The result is supposed to look like this
I was able to get the count correct using this query below
SELECT count(*) as TotCount
from (Select DISTINCT OHID, MemID
from #temp) AS TotMembers
However, when I try to use this query below to get all the results together, I am getting a count of 15 and a totally different total sum.
SELECT t.OHID,
count(TotMembers.MemID) as TotCount,
sum(t.Amount) as TotalAmount
from (Select DISTINCT OHID, MemID
from #temp) AS TotMembers
join #temp t on t.OHID = TotMembers .OHID
GROUP by t.OHID

If I understand correctly, you want to consider NULL as a valid value. The rest is just aggregation:
select t.ohid,
(count(distinct t.memid) +
(case when count(*) <> count(t.memid) then 1 else 0 end)
) as num_memid,
sum(t.amount) as total_amount
from #temp t
group by t.ohid,
The case logic might be a bit off-putting. It is just adding 1 if any values are NULL.
You might find this easier to follow with two levels of aggregation:
select t.ohid, count(*), sum(amount)
from (select t.ohid, t.memid, sum(t.amount) as amount
from #temp t
group by t.ohid, t.memid
) t
group by t.ohid

Related

How to use DISTINCT and SUM in a same SQL query on MS SQL Express

I have a situation where I need to get DISTINCT values from column "note" and then get the SUM of "price" for above records.
I tried with different queries but none of them are working fine.
SELECT DISTINCT note ,price( select SUM (price) FROM [tableName] where Archived ='0'
SELECT sum(price),(SELECT DISTINCT note , price from [tableName] where Archived ='0')
In a nutshell I need to get the sum of prices for the distinct records.
Are you looking for group by?
SELECT note, SUM(price)
FROM [tableName]
WHERE Archived = '0'
GROUP BY note;
If you want the sum over ALL the records, just use window functions like this:
SELECT note, SUM(price) as note_sum, SUM(SUM(price)) OVER () as total_sum
FROM [tableName]
WHERE Archived = '0'
GROUP BY note;
Maxbe this will be one way to do it:
select distinct sum(price) over(partition by note), note
from tablename
where Archived = 0
Here is a demo on SQLServer
If I have understood you correctly you need distinct note values and only one sum for all of them ... then something like this:
select distinct note, (select sum(price) from tablename) sum_tot
from tablename
where Archived = 0
P.S. do add expected result....

How to retrieve information from table in one statement when the result has different numbers of rows?

I want to retrieve different information in one statement from the same table and they have different number of rows.
The first select has five rows in the result and the second select has three rows because some prices have null value. I thought maybe if I can put zero instead of null so they will match the same number of rows but I don't know how to do that, or is there another solution?
select count(ID), Land
from Film_ha2911
group by Land
union
select count(ID)
from Film_ha2911
where Price is not null
group by Land;
The use of UNION implies that the number and type of columns in select must corresponding
so in your case you should use null for not select columns
select count(ID), Land
from Film_ha2911
group by Land
union
select count(ID), null
from Film_ha2911
where Price is not null
group by Land;
But in this case seems you need a left join on the subquery for land
select t1.count1, t1.land , t2.count2
from (
select count(ID) count1, Land
from Film_ha2911
group by Land
) t1
left join (
select count(ID) count2, land
from Film_ha2911
where Price is not null
group by Land;
) t2 on t1.land = t2.land
The desired result can be achieved by single SELECT without UNION.
Extra column: PriceNotNull to differentiate is Price value filled or not:
SELECT
Land,
CASE WHEN Price IS NOT NULL THEN 'True' ELSE 'False' END PriceNotNull,
COUNT(ID) AS Count_ID
FROM Film_ha2911
GROUP BY Land, CASE WHEN Price IS NOT NULL THEN 'True' ELSE 'False' END
You can just use count():
select Land, count(*) as total_rows,
count(price) as total_with_price
from Film_ha2911
group by Land;
count() counts the number of non-NULL values, so no special logic is needed to count non-NULL values. By count(id) I assume you want to count all the rows. count(*) is more explicit -- as would count(1) which some people prefer.
If you actually want this on separate rows, I would add an indicator for what the count means:
select Land, 'total rows' as which, count(*) as total_rows
from Film_ha2911
group by Land
union all
select Land, 'with price', count(price)
from Film_ha2911
group by Land;
However, I think the first version with two separate columns is more useful.

COUNT() doesn't work with GROUP BY?

SELECT COUNT(*) FROM table GROUP BY column
I get the total number of rows from table, not the number of rows after GROUP BY. Why?
Because that is how group by works. It returns one row for each identified group of rows in the source data. In this case, it will give the count for each of those groups.
To get what you want:
select count(distinct column)
from table;
EDIT:
As a slight note, if column can be NULL, then the real equivalent is:
select (count(distinct column) +
max(case when column is null then 1 else 0 end)
)
from table;
Try this:
SELECT COUNT(*), column
FROM table
GROUP BY column

Aggregate SQL Function to grab only one from each grouping

I have a table that I need to normalize with many fields In SQL-Server 2000.
It contains 2 fields which I'm using to come up with distinct combination as defined by the specs.
ID and Rate: there are multiple rows of same IDs and Rates
I first created a temp table by grouping the IDs and Rates combination.
SELECT ID, Count(*) AS IDCounts, SUM(RATE) As Total
INTO #Temp
GROUP BY ID
Now I use Distinct to find only the unique combinations. So i'll have multiple ID groups sharing same Total and IDCounts
SELECT DISTINCT Total, IDCounts
INTO #uniques
FROM #Temp
Now my question is how to join a single ID back to that distinct grouping of IDCounts and Total and put that into a new table? It doesn't matter which one of the IDs in the groups as long as I use one from the same grouping.
Keeping your temp tables (although this could all be done in a single query):
SELECT ID, Count(*) AS IDCounts, SUM(RATE) As Total
INTO #Temp
GROUP BY ID
SELECT Total, IDCounts, MIN(ID) AS SomeID
INTO #uniques
FROM #Temp
GROUP BY Total, IDCounts
Add "Min(ID) AS FirstID" to the select into #uniques.
Try something like this:
SELECT MAX(ID) AS Id, Count(*) AS IDCounts, SUM(RATE) As Total
FROM SOMETABLE
GROUP BY IDCounts, Total

unique count of the columns?

i want to get a unique count of the of multiple columns containing the similar or different data...i am using sql server 2005...for one column i am able to take the unique count... but to take a count of multiple columns at a time, what's the query ?
You can run the following selected, getting the data from a derived table:
select count(*) from (select distinct c1, c2, from t1) dt
To get the count of combined unique column values, use
SELECT COUNT(*) FROM TableName GROUP BY UniqueColumn1, UniqueColumn2
To get the unique counts of multiple individual columns, use
SELECT COUNT(DISTINCT Column1), COUNT(DISTINCT Column2)
FROM TableName
Your question is not clear what exactly you want to achieve.
I think what you're getting at is individual SUMS from two unique columns in one query. I was able to accomplish this be using
SELECT FiscalYear, SUM(Col1) AS Col1Total, SUM(Col2) AS Col2Total
FROM TableName
GROUP BY FiscalYear
If your data is not numerical in nature, you can use CASE statements
SELECT FiscalYear, SUM(CASE WHEN ColA = 'abc' THEN 1 ELSE 0 END) AS ColATotal,
SUM(CASE WHEN ColB = 'xyz' THEN 1 ELSE 0 END) AS ColBTotal
FROM TableName
GROUP BY FiscalYear
Hope this helps!