How can i select rows for specific cells from same table? - sql

I have a table with tenants and their addresses.
A tenant can have several addresses and at each address can appear several times (closed, open, modified).
The tenant appears first with an address (first) after which he can have several changes on the first address (closed, open, modified) or he can have other addresses (closed, open, modified).
How can I extract the date of closing the first address.
The problem come with a twist. The name of streets are not exactly like first addres. It can contain St., Ave. in their names.
The table look like this:
id
Tenant
code
Street
Number
Date
1
Alice
First
Abbey
5
01.01.2021
2
Alice
Modify
Abbey Ro.
5
02.01.2021
3
Alice
Open
Elm St
3
02.01.2021
4
Alice
Close
St. Abbey
5
05.01.2021
5
Bob
First
Fifth
10
01.02.2021
6
Bob
Open
Fifth Ave
222
01.02.2021
7
Bob
Close
Fifth Ave
222
05.02.2021
8
Bob
Close
Ave Fifth
10
06.02.2021
The expected result should by like this:
id
Tenant
CloseID
Street
Number
Date
1
Alice
4
Abbey
5
05.01.2021
2
Bob
8
Fifth
10
06.02.2021
I have a feel the answer is there but i can't grab it :)
Thanks in advance for your support.

you need sometihng equal in both records (first and close)
for exemple, if you are sure that 'Number' it's every time the same, and the id user it's unique you can use it
SELECT * FROM tenant WHERE Number = 10 AND Id = 5 AND code = "close"
but this it's only an example, you can use it with your tenant, beacuse you can easily run into bug
for example if the tenant have more than 1 address with the same Number
if you know where the other word (st. , ave etc ) are in the Street, you can use %
example
7 | Bob | Close | Fifth Ave | 222 | 05.02.2021
sql:
SELECT * FROM tenant WHERE Number = 10 AND Street LIKE 'Fifth%' AND code = "close"
8 | Bob | Close | Ave Fifth | 10 | 06.02.2021
sql:
SELECT * FROM tenant WHERE Number = 10 AND Street LIKE '%Fifth' AND code = "close"
otherwise you have to change the table
for example by adding the Address No. field
indicating if the address is the first, second, third etc .. for that person

I would do it like this:
with cte as(
select tenant, code, street, number, date, row_number() over (partition by tenant order by date desc) as rank
from tenants
order by date desc
)
select * from cte where rank = 1;

Related

Is this multiple join on 2 tables possible?

I have 2 tables and I am having trouble joining it to give me the desired output.
First table is called Future. It is future meetings I have.
Date Name Subject Importance Location
7/08/2020 David Work 1 London
7/08/2020 George Updates 2 New York
7/08/2020 Frank New Appointments 5 London
7/08/2020 Steph Policy 1 Paris
The second table is called Previous. It is previous meetings I have had.
Date Name Subject Importance Location Time Rating
1/08/2020 David Work 3 London 23.50 4
2/10/2018 David Emails 3 New York 18.20 3
1/08/2019 George New Appointments5 London 55.10 2
3/04/2020 Steph Dismissal 1 Paris 33.20 5
Now what I need to is to reference my previous table by name to see the previous meetings I have had with this person and I want all the data from the Previous Table there. I also need to limit it to only showing maximum 5 previous meetings with each person.
Date Name Subject Importance Location Time Rating
7/08/2020 David Work 1 London - -
1/08/2020 David Work 3 London 23.50 4
2/10/2018 David Emails 3 New York 18.20 3
7/08/2020 George Updates 2 New York - -
1/08/2019 George New Appointments5 London 55.10 2
The Name column will need to be a left join, but then i need to just do a regular join on the other columns. Also unsure how to limit the name results to a maximum of 5 of the same value. Thanks for your help in advance.
Basically, you want union all:
select m.*
from ((select Date, Name, Subject, Importance, Location, NULL as time, NULL as rating
from future
) union all
(select Date, Name, Subject, Importance, Location, time, rating
from previous
)
) m
group by name, date desc;
You can apply other conditions to this result. It is not clear what other conditions you really want, but this is a start.

SQL Server group by? [duplicate]

This question already has answers here:
Retrieving last record in each group from database - SQL Server 2005/2008
(2 answers)
Closed 4 years ago.
I'm not sure how to word my question so perhaps an example would be best. I'm looking for a function or statement that would produce the following result from a single table. For each name, return the row with largest id.
ID NAME ADDRESS
1 JOHN DOE 123 FAKE ST.
2 JOHN DOE 321 MAIN ST.
3 JOHN DOE 333 2ND AVE.
4 MARY JANE 222 1ST. AVE
5 MARY JANE 444 POPLAR ST.
6 SUZY JO 999 8TH AVE.
DESIRED RESULT
3 JOHN DOE 333 2ND AVE.
5 MARY JANE 444 POPLAR ST.
6 SUZY JO 999 8TH AVE.
One option is to use the row_number window function. This allows you to establish a row number to the result set. Then you can define the grouping and ordering within the over clause, in this case you want to partition by (group) the name field and order by the id field descending. Finally you filter those results where rn = 1 which returns the max result for each grouping.
select *
from (
select *, row_number() over (partition by name order by id desc) rn
from yourtable
) t
where rn = 1

Eliminate rows with names that are slightly different

I have in POSTGRESQL a database with a UUID, firstname (fname) and phone
uuid fname phone
1 JOHN 111
2 john 111
3 John 111
4 JOHN JAMES 111
5 Charles 222
6 Peter 222
7 James 222
8 Jimmy 222
9 Fred 333
10 Fred 333
11 Greg 333
I would like to keep only the group phone + firstname that have a similarity between at least two names. So, for example, in this case I would like to keep the phone 111 and one of the names and the phone 333 keeping the name that repeats (Fred). The phone 222 woud be eliminate as all names are not similar.
The result data would be
fname phone
John 111
Fred 333
The problem I am having is when the name is similar but it has more names (as in John and John James or when the name was mistyped, as in John and Jonh). I have tried to do the following
SELECT
m1.phone,
m1.fname,
m1.uuid
FROM
master as m1
JOIN master as m2 on m1.uuid = m2.uuid
WHERE
m1.phone = m2.phone
and m1.fname ILIKE m2.fname
ORDER BY 1
The definition of similarity is a bit vague, but this works for the data you have in the question:
select m.*
from master m
where exists (select 1
from master m2
where m2.phone = m.phone and m2.uuid <> m.uuid and
(m.fname ilike '%' || m2.fname || '%' or
m2.fname ilike '%' || m.fname || '%'
)
);
Here is a rextester.
Name matching is a complicated task and not well suited to SQL. However, you might want to look into Levenshtein distance and other string similarity metrics if this is a problem that you are facing.
Note: This keeps all names that match. If you want only one row per phone, you can use distinct on.

Oracle SQL Query to order by column value in different table

I'm rather new to sql and am struggling with a statement. For simplicity, let's say I have two tables -
Table - JourneyOrder, and Table - ItemsToBuy.
JourneyOrder has list of cities, index of a particular city in a journey and who is taking the journey.
So:
City Index Name
London 1 John
Sydney 2 John
Paris 3 John
Berlin 1 Jack
Paris 2 Jack
The other table has a list of items to buy, containing location (as in City), who needs to buy an item, and different characteristics of an item.
Item Location Weight Price Responsible
Pencil London 1 2 John
Glue London 2 5 John
Car Paris 1000 12000 John
Wallet Paris 3 20 Jack
I want to select all items a particular person needs to buy and order them by location. So if John's first route is London, I want items you can buy in London displayed first.
At the moment, I can use the following:
SELECT itb.item, itb.location, itb.price
FROM ItemsToBuy itb,
WHERE itb.responsible = 'John'
ORDER BY CASE
WHEN itb.location = 'London' THEN '1'
WHEN itb.location = 'Sydney' THEN '2'
WHEN itb.location = 'Paris' THEN '3'
Now this is obviously terrible, as I need to 'hardcode' the order by part according to the journey each responsible is taking, how can I make it so it matches location of items table to city from journey table and uses the index from the journey table when these match.
I think you just want a join:
SELECT itb.item, itb.location, itb.price
FROM ItemsToBuy itb JOIN
JourneyOrder jo
ON itb.name = jo.name AND itb.location = jo.city
WHERE itb.responsible = 'John'
ORDER BY jo.index;

Limiting records of combinations from 2 columns

looking for some help limiting the results while querying combinations between 2 columns. Here's an example of the kind of table I am working with..
id name group state
1 Bob A NY
2 Jim A NY
3 Dan A NY
4 Mike A FL
5 Tim B NY
6 Sam B FL
7 Brad B FL
8 Glen B FL
9 Ben C FL
I am trying to display all records of all combinations of "group" and "state", but limiting to displaying only up to 2 records for each combination. The result should look like the following..
id name group state
1 Bob A NY
2 Jim A NY
4 Mike A FL
5 Tim B NY
6 Sam B FL
7 Brad B FL
9 Ben C FL
Thanks for the help.
Assuming you always want the two rows for each group and state combination with the lowest id
SELECT *
FROM (SELECT a.*,
row_number() over (partition by group, state
order by id asc) rnk
FROM your_table a)
WHERE rnk <= 2
Of course, since group is a reserved word, I assume your column is actually named something else... You'd need to adjust my query to use the correct column name.