Get rollup group value in SQL Server - sql

I have a table with following data:
Name
Score
A
2
B
3
A
1
B
3
I want a query which returns the following output.
Name
Score
A
2
A
1
Subtotal: A
3
B
3
B
3
Subtotal: B
6
I am able to get "Subtotal" with group by rollup query but I want to get subtotal along with group column value.
Please help me with some SQL code

If score has at most one value per name, you can use GROUPING SETS`:
select name, sum(score) as score
from t
group by grouping sets ((name, score), (name));
If name is never null, I would just use:
coalesce(name, 'Grouping ' + name)
Otherwise you need to use grouping().

Related

Transpose in Postgresql

I am trying to design a database of customer details. Where customers can have up to two different phone numbers.
When I run the Select * command to bring out the customers that match criteria, I get this:
Name | Number
James | 12344532
James | 23232422
I would like it to display all customers with two numbers this way:
Name | Number | Number
James 12344532 23232422
John 32443322
Jude 12121212 23232422
I am using Postgresql server on Azure Data studio.
Please assist.
I tried using this command:
Select * FROM name.name,
min(details.number) AS number1,
max(details.number) AS number2
FROM name
JOIN details
ON name.id=details.id
GROUP BY name.name
I got this:
Name | Number | Number
James 12344532 23232422
John 32443322 32443322
Jude 12121212 23232422
Customers with just 1 phone number gets duplicated in the table. How do I go about this?
I would aggregate the numbers into an array, then extract the array elements:
select n.name,
d.numbers[1] as number_1,
d.numbers[2] as number_2
from name n
join (
select id, array_agg(number) as numbers
from details
group by id
) d on d.id = n.id
order by name;
This is also easy to extend if you have more than two numbers.
Try using the following query:
SELECT
Name,
MIN(CASE WHEN rn = 1 THEN Number END) AS Number1,
MIN(CASE WHEN rn = 2 THEN Number END) AS Number2
FROM
(SELECT
Name, Number,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Number) AS rn
FROM name) t
GROUP BY Name
This query will use the ROW_NUMBER() function to assign a unique row number to each phone number for each customer. The ROW_NUMBER() function is ordered by the Number column, so the lowest number will have a row number of 1, and the second lowest number will have a row number of 2, etc.
Then we use the outer query to group customer by name and use MIN() function to get the first and second number based on the row number.
This query will return the desired output, with two columns, one showing the customer's first phone number and the other showing their second phone number.
Note: The query above assumes that the phone number is unique for each customer. If a customer has duplicate phone numbers, the query will return the first one it encounters.

duplication of rows in table

I have a table which has many rows which are same, except for the id column. How can I show only one row for other duplicate row?
id name roll_number
1 a 1
2 b 2
3 a 1
4 b 2
5 c 3
6 d 4
7 d 4
show output like this
id name roll_number
1 a 1
2 b 2
5 c 3
6 d 4
We can use DISTINCT ON here:
SELECT DISTINCT ON (name) id, name, roll_number
FROM yourTable
ORDER BY name, id;
This query is selecting one record with the lowest id from each group of records having the same name.
Simple aggregation using min
select Min(id), name,roll_number
from t
group by name, roll_number
You could use the numpy.unique(filt, trim='fb') function:
>>> import numpy as np
>>> np.unique(array)
This problem requires to "filter out" tuples during the projection based on groups. The solution is to use distinct on.
SELECT DISTINCT ON (name, roll_number) id, name, roll_number
FROM table
ORDER BY name, id;
it basically creates groups by the attributes within the "DISTINCT_ON" and non-deterministically chooses one tuple, which it outputs.

SQL - Count Results of 2 Columns

I have the following table which contains ID's and UserId's.
ID UserID
1111 11
1111 300
1111 51
1122 11
1122 22
1122 3333
1122 45
I'm trying to count the distinct number of 'IDs' so that I get a total, but I also need to get a total of ID's that have also seen the that particular ID as well... To get the ID's, I've had to perform a subquery within another table to get ID's, I then pass this into the main query... Now I just want the results to be displayed as follows.
So I get a Total No for ID and a Total Number for Users ID - Also would like to add another column to get average as well for each ID
TotalID Total_UserID Average
2 7 3.5
If Possible I would also like to get an average as well, but not sure how to calculate that. So I would need to count all the 'UserID's for an ID add them altogether and then find the AVG. (Any Advice on that caluclation would be appreciated.)
Current Query.
SELECT DISTINCT(a.ID)
,COUNT(b.UserID)
FROM a
INNER JOIN b ON someID = someID
WHERE a.ID IN ( SELECT ID FROM c WHERE GROUPID = 9999)
GROUP BY a.ID
Which then Lists all the IDs and COUNT's all the USERID.. I would like a total of both columns. I've tried warpping the query in a
SELECT COUNT(*) FROM (
but this only counts the ID's which is great, but how do I count the USERID column as well
You seem to want this:
SELECT COUNT(DISTINCT a.ID), COUNT(b.UserID),
COUNT(b.UserID) * 1.0 / COUNT(DISTINCT a.ID)
FROM a INNER JOIN
b
ON someID = someID
WHERE a.ID IN ( SELECT ID FROM c WHERE GROUPID = 9999);
Note: DISTINCT is not a function. It applies to the whole row, so it is misleading to put an expression in parentheses after it.
Also, the GROUP BY is unnecessary.
The 1.0 is because SQL Server does integer arithmetic and this is a simple way to convert a number to a decimal form.
You can use
SELECT COUNT(DISTINCT a.ID) ...
to count all distinct values
Read details here
I believe you want this:
select TotalID,
Total_UserID,
sum(Total_UserID+TotalID) as Total,
Total_UserID/TotalID as Average
from (
SELECT (DISTINCT a.ID) as TotalID
,COUNT(b.UserID) as Total_UserID
FROM a
INNER JOIN b ON someID = someID
WHERE a.ID IN ( SELECT ID FROM c WHERE GROUPID = 9999)
) x

Complex SQL query or queries

I looked at other examples, but I don't know enough about SQL to adapt it to my needs. I have a table that looks like this:
ID Month NAME COUNT First LAST TOTAL
------------------------------------------------------
1 JAN2013 fred 4
2 MAR2013 fred 5
3 APR2014 fred 1
4 JAN2013 Tom 6
5 MAR2014 Tom 1
6 APR2014 Tom 1
This could be in separate queries, but I need 'First' to equal the first month that a particular name is used, so every row with fred would have JAN2013 in the first field for example. I need the 'Last" column to equal the month of the last record of each name, and finally I need the 'total' column to be the sum of all the counts for each name, so in each row that had fred the total would be 10 in this sample data. This is over my head. Can one of you assist?
This is crude but should do the trick. I renamed your fields a bit because you are using a bunch of "RESERVED" sql words and that is bad form.
;WITH cte as
(
Select
[NAME]
,[nmCOUNT]
,ROW_NUMBER() over (partition by NAME order by txtMONTH ASC) as 'FirstMonth'
,ROW_NUMBER() over (partition by NAME order by txtMONTH DESC) as 'LastMonth'
,SUM([nmCOUNT]) as 'TotNameCount'
From Table
Group by NAME, [nmCOUNT]
)
,cteFirst as
(
Select
NAME
,[nmCOUNT]
,[TotNameCount]
,[txtMONTH] as 'ansFirst'
From cte
Where FirstMonth = 1
)
,cteLast as
(
Select
NAME
,[txtMONTH] as 'ansLast'
From cte
Where LastMonth = 1
Select c.NAME, c.nmCount, c.ansFirst, l.ansLast, c.TotNameCount
From cteFirst c
LEFT JOIN cteLast l on c.NAME = l.NAME

Difference in output from two SQL queries

What is the difference between the two SQL queries below other than Query2 returning an additional field? Are there any possible scenarios where the output of the two queries would be different (other than the additional field in Query2)
Query1:
SELECT Field1, COUNT(*)
FROM Table1
GROUP BY Field1
HAVING COUNT(*) > 1
Query2:
SELECT Field1, Field2, COUNT(*)
FROM Table1
GROUP BY Field1, Field2
HAVING COUNT(*) > 1
Absolutely, these are different. Query2's Group By clause specifies an extra field. That means when the results are aggregated, they will be aggregated for the combined unique values of Field1 AND Field2. That is, two records are aggregated if and only if both Field1 and Field2 are equal.
For example:
SELECT Profession, Count(*)
FROM People
GROUP BY Profession
HAVING Count(*) > 1
will return a list of professions with associated counts like:
Software Developer, 10
PM, 5
Tester, 2
whereas:
SELECT Profession, Gender, Count(*)
FROM People
GROUP BY Profession, Gender
HAVING Count(*) > 1
will return a list of professions broken out by gender like:
Software Developer, Male, 5
Sofware Developer, Female, 5
PM, Male, 3
PM, Female, 2
Tester, Male, 2
Edit with additional requested information:
You can retrieve counts of professions with rows for both genders via:
SELECT Profession, Count(*)
FROM People
GROUP BY Profession
HAVING SUM(case Gender when 'Female' then 1 else 0 end) > 0 AND SUM(case Gender when 'Male' then 1 else 0 end) > 0
It gets a bit hairy (need subqueries) if you also need associated gender counts
Extra group by clause in query 2 filters records.To know more look at below example.
test data:
id name
1 a
2 b
3 a
4 a
So when I say group by name,sql first filters out distinct records for name which goes like below for the below query
select name,sum(id)
from test
group by name
--first filter out distinct values for group by column (here name)
a
b
--next for each distinct record ,how many values fall into that category..
a 1 a
4 a
3 a
b 2 b
So from the above groups ,now you can calculate any aggregations on the group in our case,it is sum,so next output will go some thing like this
a 8
b 2
As you can see from above output,you also can calculate,any aggregation on group (here a and b values) ,like give me count(id),len(name) on group like below
select name,len(name),sum(id)
from test
group by name
The same thing happens when you group by another field,lets say like below
select id,name
from
test
group by id,name
so in above case,sql first filters alldistinct records for id,name
1 a
2 b
3 a
4 a
next step is to get records which fall for each group
groupby columns --columns which fall into this
1 a 1 a
2 b 2 b
3 a 3 a
4 a 4 a
Now you can calculate aggergations on above groups.hope this helps in visualizing your group by.further having will eliminate groups after group by phase,where will eliminate record before group by phase