SQL distinct query over two tables - sql

I would like to find the distinct reviews (by year) for each employee showing only the most recent review (by year)
Employee List Employee Reviews
Number | Employee Name GUID | Number | Year
1234 John x5848 1234 2016
4526 Jim xd565 1234 2015
1123 Pam cr484 1123 2016
Result Needed:
Number | Name | GUID | Year
1234 John x5848 2016
1123 Pam cr484 2016
I can't figure out how to write a SQL query that would return me the above results. Anyone have any experience with a query like this or similar?

You can rank your records by giving row numbers to them:
select
guid, number, year,
row_number() over (partition by number order by year desc) as rn
from employee_reviews;
This gives the newest records (order by year desc) per employee (partition by number) row number 1. Hence:
select emp.number, emp.name, rev.guid, rev.year
from employee amp
join
(
select
guid, number, year,
row_number() over (partition by number order by year desc) as rn
from employee_reviews
) rev on rev.number = emp.number and rev.rn = 1;

Related

SQL How to take the minium for multiple fields?

Consider the following data set that records the product sold, year, and revenue from that particular product in thousands of dollars. This data table (YEARLY_PRODUCT_REVENUE) is stored in SQL and has many more rows.
Year | Product | Revenue
2000 Table 100
2000 Chair 200
2000 Bed 150
2010 Table 120
2010 Chair 190
2010 Bed 390
Using SQL, for every year I would like to find the product that has the maximum revenue.
That is, I would like my output to be the following:
Year | Product | Revenue
2000 Chair 200
2010 Bed 390
My attempt so far has been this:
SELECT year, product, MIN(revenue)
FROM YEARLY_PRODUCT_REVENUE
GROUP BY article, month;
But when I do this, I get multiple-year values for distinct products. For instance, I'm getting the output below which is an error. I'm not entirely sure what the error here is. Any help would be much appreciated!
Year | Product | Revenue
2000 Table 100
2000 Bed 150
2010 Table 120
2010 Chair 190
You don't mention the database so I'll assume it's PostgreSQL. You can do:
select distinct on (year) * from t order by year, revenue desc
You want filtering rather than aggregation. We can use window functions (which most databases support) to rank yearly product sales, and then retain only the top selling product per year.
select *
from (
select r.*, rank() over(partition by year order by revenue desc) rn
from yearly_product_revenue r
) r
where rn = 1;
Here is a shorter solution if your database support the standard WITH TIES clause:
select *
from yearly_product_revenue r
order by rank() over(partition by year order by revenue desc)
fetch first row with ties

Select car of max(date) for every employee [duplicate]

This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
Select First Row of Every Group in sql [duplicate]
(2 answers)
Return row with the max value of one column per group [duplicate]
(3 answers)
GROUP BY with MAX(DATE) [duplicate]
(6 answers)
How to return only latest record on join [duplicate]
(6 answers)
Closed last year.
I would need a code for the following problem:
I have a table like this:
Employee
Year
Month
Car
Tom
2021
9
Ford
Tom
2021
10
Ford
Tom
2021
11
Ford
Tom
2021
12
Renault
Tom
2022
1
Renault
Mark
2021
12
VW
Mark
2022
1
VW
Mark
2022
2
VW
Joe
2021
8
Opel
Joe
2021
9
Tesla
Joe
2021
10
Ferrari
And I would need the car used by the employee for the last possible date. So the result should be:
Employee
Car
Tom
Renault
Mark
VW
Joe
Ferrari
With:
select employee, max(year || month) from table.cars
group by employee
I get the max(date) for every employee, but I do not know how to join the cars to the max(date).
How can I get the result I want?
You can use ROW_NUMBER() analytic function such as
SELECT Employee, Car
FROM (SELECT ROW_NUMBER() OVER
(PARTITION BY Employee ORDER BY year DESC, month DESC) AS rn,
c.*
FROM cars c)
WHERE rn = 1
provided that the data type of the year and month are of string type, then you can replace the part ORDER BY year DESC, month DESC with
ORDER BY TO_NUMBER(TRIM(year)) DESC, TO_NUMBER(TRIM(month)) DESC
with t as
(
select *,
row_number() over (partition by employee order by year desc, month desc) rn
from cars
)
select employee, car
from t
where rn = 1
Try this:
select employee, car
from (
Select *, ROW_NUMBER(partition by employee order by year, month DESC) as row_number
from cars
)a
Where row_number = 1

How to use FIND_IN_SET and sum column in my SQL query

Can anyone help me? I have a table result like this:
id_user
score
type
001
30
play
001
40
play
001
30
redeem
002
20
play
002
30
redeem
I want to sum column score group by id_user base on type 'play' and after that I want show ranking using find_in_set. Like this is the result of the table that I want to display:
id_user
total
rank
001
70
1
002
20
2
Previously I used the rank() function in MySQL version 10.4, but it does not work in MySQL version 15.1. This is my previous query:
SELECT id_user, SUM(score) AS total,
RANK() OVER (ORDER BY total DESC) AS rank
FROM result
WHERE type='play'
GROUP BY id_user
I have made some changes in your query. It's working now. Instead of column alias total SUM(score) needs to be used in order by clause of Rank() function's over(). And since Rank is a reserve word I used rnk instead.
DB-Fiddle:
create table result (id_user varchar(5), score int, type varchar(20));
insert into result values('001',30 ,'play');
insert into result values('001',40 ,'play');
insert into result values('001',30 ,'redeem');
insert into result values('002',20 ,'play');
insert into result values('002',30 ',redeem');
Query:
select id_user, SUM(score) AS total, RANK() OVER (ORDER BY SUM(score) DESC) AS rnk FROM result where type='play' GROUP BY id_user
Output:
id_user
total
rnk
001
70
1
002
20
2
db<>fiddle here
If your MySQL version doesn't support rank() you can use subquery to achieve same result:
Query:
select id_user, SUM(score) AS total,
coalesce((select count(distinct id_user) from result r2
where type='play'
group by id_user
having sum(r2.score)>sum(r.score) ),0)+1 AS rnk
FROM result r where type='play'
GROUP BY id_user
Output:
id_user
total
rnk
001
70
1
002
20
2
db<>fiddle here

Firebird Query- Return first row each group

In a firebird database with a table "Sales", I need to select the first sale of all customers. See below a sample that show the table and desired result of query.
---------------------------------------
SALES
---------------------------------------
ID CUSTOMERID DTHRSALE
1 25 01/04/16 09:32
2 30 02/04/16 11:22
3 25 05/04/16 08:10
4 31 07/03/16 10:22
5 22 01/02/16 12:30
6 22 10/01/16 08:45
Result: only first sale, based on sale date.
ID CUSTOMERID DTHRSALE
1 25 01/04/16 09:32
2 30 02/04/16 11:22
4 31 07/03/16 10:22
6 22 10/01/16 08:45
I've already tested following code "Select first row in each GROUP BY group?", but it did not work.
In Firebird 2.5 you can do this with the following query; this is a minor modification of the second part of the accepted answer of the question you linked to tailored to your schema and requirements:
select x.id,
x.customerid,
x.dthrsale
from sales x
join (select customerid,
min(dthrsale) as first_sale
from sales
group by customerid) p on p.customerid = x.customerid
and p.first_sale = x.dthrsale
order by x.id
The order by is not necessary, I just added it to make it give the order as shown in your question.
With Firebird 3 you can use the window function ROW_NUMBER which is also described in the linked answer. The linked answer incorrectly said the first solution would work on Firebird 2.1 and higher. I have now edited it.
Search for the sales with no earlier sales:
SELECT S1.*
FROM SALES S1
LEFT JOIN SALES S2 ON S2.CUSTOMERID = S1.CUSTOMERID AND S2.DTHRSALE < S1.DTHRSALE
WHERE S2.ID IS NULL
Define an index over (customerid, dthrsale) to make it fast.
in Firebird 3 , get first row foreach customer by min sales_date :
SELECT id, customer_id, total, sales_date
FROM (
SELECT id, customer_id, total, sales_date
, row_number() OVER(PARTITION BY customer_id ORDER BY sales_date ASC ) AS rn
FROM SALES
) sub
WHERE rn = 1;
İf you want to get other related columns, This is where your self-answer fails.
select customer_id , min(sales_date)
, id, total --what about other colums
from SALES
group by customer_id
So simple as:
select CUSTOMERID min(DTHRSALE) from SALES group by CUSTOMERID

Retrieve highest value from sql table

How can retrieve that data:
Name Title Profit
Peter CEO 2
Robert A.D 3
Michael Vice 5
Peter CEO 4
Robert Admin 5
Robert CEO 13
Adrin Promotion 8
Michael Vice 21
Peter CEO 3
Robert Admin 15
to get this:
Peter........4
Robert.......15
Michael......21
Adrin........8
I want to get the highest profit value from each name.
If there are multiple equal names always take the highest value.
select name,max(profit) from table group by name
Since this type of request almost always follows with "now can I include the title?" - here is a query that gets the highest profit for each name but can include all the other columns without grouping or applying arbitrary aggregates to those other columns:
;WITH x AS
(
SELECT Name, Title, Profit, rn = ROW_NUMBER()
OVER (PARTITION BY Name ORDER BY Profit DESC)
FROM dbo.table
)
SELECT Name, Title, Profit
FROM x
WHERE rn = 1;