Order pairs/triplets of rows given the sum of a column - sql

I'd like to order pairs (or group of 3,4 etc.) of rows given the SUM of a certain value.
The rows are consecutive based on the concatenation of Name+Surname+Age
To better understand given the following table:
ID Name Surname Age Salary
------------------------------
1 John Smith 30 2
2 John Smith 30 10
3 Rick James 22 300
4 Rick James 22 1000
5 Rick James 22 5
6 Mike Brown 50 200
7 Mike Brown 50 20
I'd like to have a final table that should be ordered DESC by the sum of Salary of each Name+Surname+Age and keeping the rows with same Name+Surname+Age next to each others despite the ID column is different. This would be the expected result:
ID Name Surname Age Salary
------------------------------
3 Rick James 22 300
4 Rick James 22 1000
5 Rick James 22 5
6 Mike Brown 50 200
7 Mike Brown 50 20
1 John Smith 30 2
2 John Smith 30 10
As you can see the rows with Name+Surname+Age = "Rick Jams 22" are on the top since their total sum would be 1305, followed by "Mike Brown 50" (sum = 220) and "John Smith 30" (sum = 12).
Additionally, the number of rows has to be the same in the resulting table.
How can I do that using Oracle SQL?
Thanks for any help

SELECT t.*,
COALESCE(SUM(salary) OVER (PARTITION BY name, surname, age), 0) ss
FROM mytable t
ORDER BY
ss DESC

Try this:
SELECT ID, Name, Surname, Age, Salary
FROM (
SELECT ID, Name, Surname, Age, Salary,
SUM(Salary) OVER (PARTITION BY Name, Surname, Age) AS sum_of_sal
FROM mytable) t
ORDER BY sum_of_sal DESC, ID
The query uses the window version of SUM in order to calculate the sum of salaries per Name, Surname, Age partition. We can use this field in an outer query to do the sorting.

or try this
SELECT ID, Name, Surname, Age, Salary
FROM mytable
ORDER BY SUM(Salary) OVER (PARTITION BY Name, Surname, Age) DESC, ID

Related

SQL average Percentage by group

I have table1 with some sample record (would have more than 100 records)
lastname courtesy
Lane 3
Lane 4
Lane 5
Lane 12
Santana 4
Santana 5
My query to get the ave percent group by lastname and did not group by lastname
you can see Lane and Santana still not group.
Please correct the query. Thank you.
SELECT
lastname,
courtesy,
percentage = AVG(courtesy) * 100 / SUM(AVG(courtesy)) OVER (PARTITION BY lastname)
FROM echo
GROUP BY
lastname, courtesy
the results
lastname courtesy percentage
Lane 3 12
Lane 4 16
Lane 5 20
Lane 12 50
Santana 4 44
Santana 5 55
the results look like this
lastname percentage
Lane 16 (4/24)
Satana 22 (2/9)
count (lastname) / sum (courtesy) group by lastname
I think this is the logic that you want:
SELECT lastname,
SUM(SUM(courtesy)) OVER (ORDER BY lastname),
COUNT(*) * 1.0 / SUM(courtesy)
FROM echo
GROUP BY lastname;

SQL query to get only rows match the condition based on two separated columns under one 'group by'

The simple SELECT query would return the data as below:
Select ID, User, Country, TimeLogged from Data
ID User Country TimeLogged
1 Samantha SCO 10
1 John UK 5
1 Andrew NZL 15
2 John UK 20
3 Mark UK 10
3 Mark UK 20
3 Steven UK 10
3 Andrew NZL 15
3 Sharon IRL 5
4 Andrew NZL 25
4 Michael AUS 5
5 Jessica USA 30
I would like to return a sum of time logged for each user grouped by ID
But for only ID numbers where both of these values Country = UK and User = Andrew are included within their rows.
So the output in the above example would be
ID User Country TimeLogged
1 John UK 5
1 Andrew NZL 15
3 Mark UK 30
3 Steven UK 10
3 Andrew NZL 15
First you need to identify which IDs you're going to be returning
SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew';
and based on that, you can then filter to aggregate the expected rows.
SELECT ID,
[User],
Country,
SUM(Timelogged) as Timelogged
FROM mytable
WHERE (Country='UK' OR [User]='Andrew')
AND ID IN( SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew')
GROUP BY ID, [User], country;
So, you have described what you need to write almost perfectly but not quite. Your result table indicates that you want Country = UK OR User = Andrew, rather than AND
You need to select and group by, then include a WHERE:-
Select ID, User, Country, SUM(Timelogged) as Timelogged from mytable
WHERE Country='UK' OR User='Andrew'
Group by ID, user, country

Query to find least fifth salaried employee [duplicate]

This question already has answers here:
Select second most minimum value in Oracle
(3 answers)
Closed 4 years ago.
EMPID NAME DEPTID SALARY
---------- ------------------------------------------ --
101 surendra 201 1000
102 narendra 202 2000
103 rajesh 203 3000
104 ramesh 203 2000
105 hanumanth 202 10000
a) Write a Query to find least 5th (Least salary in 5th position from
least salary in the order) salaried employee?
b) Query to find the highest earning employee in each department
a) Write a Query to find least 5th (Least salary in 5th position from least salary in the order) salaried employee?
SELECT EMPID,NAME,DEPTID,SALARY
FROM
(
SELECT EMPID,NAME,DEPTID,SALARY, DENSE_RANK() OVER (ORDER BY SALARY) AS RN
FROM Table1
)
WHERE RN=5
b) Query to find the highest earning employee in each department
SELECT EMPID,NAME,DEPTID,SALARY
FROM
(
SELECT EMPID,NAME,DEPTID,SALARY,
DENSE_RANK() OVER (PARTITION BY DEPTID ORDER BY SALARY DESC) AS RN
FROM Table1
)
WHERE RN=1
Demo
http://sqlfiddle.com/#!4/63ce0/12
Let's assume we have a table named EmployeeSalary which has 3 columns:
Id
Name
Salary
Salary might be same for multiple employee according to the following table data
Id Name Salary
----------
6 Belalo 74
1 Karim 100
5 dIPU 100
4 Satter 102
9 Kiron 120
10 Rash 120
11 Harun 130
13 Baki 130
12 Munshi 132
2 Rahim 500
7 Kaif 987
8 Sony 987
3 Belal 4000
Now the query will be
SELECT A.Salary
FROM
(
SELECT DISTINCT Salary,
DENSE_RANK() OVER (ORDER BY Salary) AS Ranks
FROM [dbo].[EmployeeSalary]
) A
WHERE A.Ranks=5

How to select only details of min value only in SQL?

I could get the minimum percentage of two values, but I need only the name, and ID in the select.
ID NAME CITY ONE TWO
--------------------------------------------------
2 Morales Los Angeles 40 10
1 John New York 60 20
4 Mary San Diego 10 10
I need to get the min value of one/two, and to only appear this as a result:
ID NAME
---------
4 Mary
Select ID, NAME
from MYTABLE
where least(ONE,TWO) = (select min(least(ONE,TWO)) from MYTABLE);
If you don't want Morales, then you can do this :
Select ID, NAME
from MYTABLE
where id =
(select id from
(select id from MYTABLE order by least(ONE,TWO), ONE*TWO)
where rownum <= 1);

selecting a row using MIN or ROWNUM

I have a oracle table which is similar to the one below which stores people's lastname firstname and age. If last name is same people belong to same family.
LastName FirstName Age
===========================
1 miller charls 20
2 miller john 30
3 anderson peter 45
4 Bates andy 50
5 anderson gary 60
6 williams mark 15
I need to write a oracle sql query to
select youngest person from each family. output shd select rows 1,3,4 and 6
How do I do this ?
Another way, a bit shorter:
select lastname
, max(firstname) keep(dense_rank first order by age) as first_name
, max(age) keep(dense_rank first order by age) as age
from you_table_name
group by lastname
order by lastname
Result:
LASTNAME FIRST_NAME AGE
-------- ---------- ----------
Bates andy 50
anderson peter 45
miller charls 20
williams mark 15
And SQLFiddle Demo
DENSE_RANK() is a ranking function which generates sequential number and for ties the number generated is the same. I prefer to use DENSE_RANK() here considering that a family can have twins, etc.
SELECT Lastname, FirstName, Age
FROM
(
SELECT Lastname, FirstName, Age,
DENSE_RANK() OVER (PARTITION BY LastName ORDER BY Age) rn
FROM tableName
) a
WHERE a.rn = 1
SQLFiddle Demo
With Standard SQL I would do as this...
select *
from family f1
where (
select count(*)
from family f2
where
f2.lastname = f1.lastname
and
f2.age <= f1.age) <= 1
order by lastname;
This SQL gives you possibilities to pick x youngest/oldest in a family. Just modify the f2.age <= f1.age to e.g. f2.age >= f1.age, and the <= 1 to e.g. <=10 (to get top 10 youngest/oldest in a family).
SQLfiddle