select max sum of user from table, as user with maximum amount? - sql

I have a table as
create table mock_sales
(
first_name character varying,
last_name character varying,
amount integer
);
insert into mock_sales(first_name, last_name, amount)
values('ted','mosby', 100),
('lily', 'aldrin', 400),
('ted', 'mosby', 350),
('barney', 'Stinson',180)
Output Desired
Person with max sum amount
ted mosby // As ted mosby sum = 450 (100 + 350), which is largest
I tried
Select first_name, last_name from mock_sales group by first_name, last_name where amount in (
select max(amount) from t
(select sum(amount) as amount from mock_sales as t group by first_name, last_name)
or
select t.first_name, t.last_name from mock_sales where max(amount) == t.amount and t.amount in (
Select first-name, last_name, sum(amount) as amount from mock_sales as t group by first_name, last_name)
But they both gave syntax errors. Any help will be appreciated.
Having trouble joining the result of 2 queries.

You can just group records having the same first/last name, order the results and keep the first row only:
select first_name, last_name, sum(amount) total_amount
from mock_sales
group by first_name, last_name
order by total_amount desc
limit 1
If you want to allow ties, then it is a bit different. In Postgres, you can use window functions:
select *
from (
select first_name, last_name, sum(amount) total_amount,
rank() over(order by sum(amount) desc) rn
from mock_sales
group by first_name, last_name
) t
where rn = 1

Since you want the sum instead of max value so, try this instead:
SELECT first_name,last_name, SUM(amount) AS amount FROM mock_sales
GROUP BY first_name,last_name ORDER BY amount DESC LIMIT 1;

Related

Is this SQL query possible? I am trying to get the least frequent names in this table

This is a toy public table in google BigQuery:
The table contains the names given to people in the US at birth and the frequency of those names for each state and year from 1910 to 2020
Columns: name, year, state, number, gender
names toy table
I am trying to get the LEAST popular names (names with lowest 'number' column) each year.
I am not sure this is possible with this schema.
Depending on how you want to handle a tie, you want rank or row_number.
select
*
from (
select
*,
row_number() over (partition by year order by name_frequency) as rn
from (
select
year,
name,
sum(number) as name_frequency
from `bigquery-public-data.usa_names.usa_1910_2013`
group by
year,
name
) sub1
) sub2
where rn = 1
Consider below approach
select * from (
select year, gender, name, sum(number) number
from `bigquery-public-data.usa_names.usa_1910_2013`
group by year, gender, name
qualify 1 = row_number() over(partition by year, gender order by number)
)
pivot (any_value(name) name, any_value(number) number for gender in ('M', 'F'))
# order by year desc
with output (just top 9 shown)
In reality - there are many names that have same least frequency - to get all of them - use below approach
select * from (
select year, gender, name, sum(number) number
from `bigquery-public-data.usa_names.usa_1910_2013`
group by year, gender, name
qualify 1 = dense_rank() over(partition by year, gender order by number)
)
pivot (string_agg(name) name, any_value(number) number for gender in ('M', 'F'))
with output
while if you would look for most frequent - you would use below
select * from (
select year, gender, name, sum(number) number
from `bigquery-public-data.usa_names.usa_1910_2013`
group by year, gender, name
qualify 1 = dense_rank() over(partition by year, gender order by number desc)
)
pivot (string_agg(name) name, any_value(number) number for gender in ('M', 'F'))
with just one most frequent name per year/gender

Select Only min and max value per group

How to select only 1 of min and max value of tap_time = tap_type 1(min) and 0(max) heres my unfinished query! Hope someone can help me.
use RFIDEmployee_DB
select *
from (
select FK_student_ID, Tap_Type, FK_Terminal_ID, Student_No, Last_Name, First_Name, Middle_Name, Tap_Time
from tbGateEntry
inner join tbStudentInfo on tbGateEntry.FK_student_ID = tbStudentInfo.ID
) t
order by Last_Name , Tap_Time
Rank function could help you choose first 1 by each type, change column name based on your requirement
use RFIDEmployee_DB
select *
from (
select FK_student_ID, Tap_Type, FK_Terminal_ID, Student_No, Last_Name, First_Name, Middle_Name, Tap_Time, ROW_NUMBER() OVER (PARTITION BY Tap_Type ORDER BY Tap_Time) R
from tbGateEntry
inner join tbStudentInfo on tbGateEntry.FK_student_ID = tbStudentInfo.ID
) t
where R = 1
order by Last_Name , Tap_Time

Finding Duplicate Rows in a Table

I am trying to find out how many duplicate records I have in a table. I can use count, but I'm not sure how best to eliminate records where the count is only 1.
select first_name, last_name, start_date, count(1)
from employee
group by first_name, last_name, start_date;
I can try to order by the count, but I am still not eliminating those with a count of one.
you can use having clause as having Count(*) > 1 after group by like this :
select
first_name,
last_name,
start_date,
Count(*) AS Count
from
employee
group by
first_name,
last_name,
start_date
having
Count(*) > 1

Retrieving rows randomly in pl/sql query

I have a table (t1). I know how to retrieve percentage of set randomly.
What I want is to insert 30% of randomly selected rows into t2, and insert remaining 70% into table t3.
Is there any other way except inserting 30% into table t2 and than compare t2 with t1 and insert into t3? This method is not good for me since table is huge.
ps. oracle version - 11g
Look into ora_hash. Generate a hash using the table's PK (or some similar column combination) with a bucket of 9, and those with a 0-6 go in one table, and those with 7,8 or 9 go in another.
would an insert all work? here is one I did with the HR employees table so I ordered by random and took 30 percent of them. those ones got an indicator of one. I did a union all on the whole table and give it an indicator of 0. I took the max for the indicator then did an insert all. if the indicator is 1 into the first table otherwise the remaining 70% into the second.
INSERT ALL
WHEN (table_one_ind = 1) THEN
INTO table_one
(
employee_id,
first_name,
last_name,
email,
hire_date,
job_id
)
VALUES
(
employee_id,
first_name,
last_name,
email,
hire_date,
job_id
)
ELSE
INTO table_two
(
employee_id,
first_name,
last_name,
email,
hire_date,
job_id
)
VALUES
(
employee_id,
first_name,
last_name,
email,
hire_date,
job_id
)
SELECT MAX (table_one_ind) table_one_ind,
employee_id,
first_name,
last_name,
email,
hire_date,
job_id
FROM
(SELECT t.*,
1 AS table_one_ind
FROM
( SELECT * FROM employees ORDER BY dbms_random.value
) t
WHERE rownum <=
( SELECT ceil(COUNT(*)*.3) FROM employees
)
UNION ALL
SELECT t.*, 0 FROM employees t
)
GROUP BY employee_id,
first_name,
last_name,
email,
hire_date,
job_id

SQl server query multiple aggregate columns

I need to write a query in sql server to data get like this.
Essentially it is group by dept, race, gender and then
SUM(employees_of_race_by_gender),Sum(employees_Of_Dept).
I could get data of first four columns, getting sum of employees in that dept is becoming difficult.
Could you pls help me in writing the query?
All these details in same table Emp. Columns of Emp are Emp_Number, Race_Name,Gender,Dept
Your "num_of_emp_in_race" is actually by Gender too
SELECT DISTINCT
Dept,
Race_name,
Gender,
COUNT(*) OVER (PARTITION BY Dept, Race_name, Gender) AS num_of_emp_in_race,
COUNT(*) OVER (PARTITION BY Dept) AS num_of_emp_dept
FROM
MyTable
You should probably have this
COUNT(*) OVER (PARTITION BY Dept, Gender) AS PerDeptRace
COUNT(*) OVER (PARTITION BY Dept, Race_name) AS PerDeptGender,
COUNT(*) OVER (PARTITION BY Dept, Race_name, Gender) AS PerDeptRaceGender,
COUNT(*) OVER (PARTITION BY Dept) AS PerDept
Edit: the DISTINCT appears to be applied before the COUNT (which would odd based on this) so try this instead
SELECT DISTINCT
*
FROM
(
SELECT
Dept,
Race_name,
Gender,
COUNT(*) OVER (PARTITION BY Dept, Race_name, Gender) AS num_of_emp_in_race,
COUNT(*) OVER (PARTITION BY Dept) AS num_of_emp_dept
FROM
MyTable
) foo
Since the two sums you're looking for are based on a different aggregation, you need to calculate them separately and join the result. In such cases I first build the selects to show me the different results, making it easy to catch errors early:
SELECT Dept, Gender, race_name, COUNT(*) as num_of_emp_in_race
FROM Emp
GROUP BY 1, 2, 3
SELECT Dept, COUNT(*) as num_of_emp_in_dept
FROM Emp
GROUP BY 1
Afterwards, joining those two is pretty straight forward:
SELECT *
FROM ( first statement here ) as by_race
JOIN ( second statement here ) as by_dept ON (by_race.Dept = by_dept.Dept)