Find last match with latest inserted name in table - sql

I have a table PersonalInfo having columns such as Id, Name, Address.
Suppose I have following data
1 John US
2 Mark UK
3 John UK
4 David US
Now when I insert following new record
5 John China
I want to update the last record having same name as the new one for example as shown here the record 3 John UK will be updated to 3 John China.
When I insert the 5th record the table should be
1 John US
2 Mark UK
3 John China
4 David US
5 John China
what sql query should I use?

Assuming the Id is auto-incremented, it would be the highest value for that Name and Address combination.
UPDATE PersonalInfo
SET Address = 'US'
WHERE ID = (SELECT MAX(Id)
FROM PersonalInfo
WHERE Name = 'John'
AND Address = 'UK'
)

Related

Update all peers with value from the single peer having data in a column

I have a table customers with multiple rows per name. I have the SELECT query reporting the right information, but I'm having trouble formulating the UPDATE statement.
How can I build an UPDATE statement to make all rows with the same name match on address, i.e. copy from the peer row with address data.
Here's my SELECT statement:
SELECT *
FROM customers b
WHERE (
SELECT count(*)
FROM customers b
WHERE a.name = b.name
) > 1
GROUP BY a.customerid
Example results:
Record 1 - John Smith / 123 Address ln
Record 2 - John Smith / <blank address>
Record 3 - John Smith / <blank address>
Record 4 - Tim Johnson / 456 Test Ave
Record 5 - Tim Johnson / <blank address>
Desired result:
Record 1 - John Smith / 123 Address ln
Record 2 - John Smith / 123 Address ln
Record 3 - John Smith / 123 Address ln
Record 4 - Tim Johnson / 456 Test Ave
Record 5 - Tim Johnson / 456 Test Ave
There are over 10,000 duplicated rows, so I'm having trouble writing sufficient constraints to build a 'catch-all' UPDATE statement to pick a 'parent' row as template for its 'child' rows. Every UPDATE statement I build seems to produce results like the following:
Record 1 - John Smith / 123 Address ln
Record 2 - John Smith / 123 Address ln
Record 3 - John Smith / 123 Address ln
Record 4 - Tim Johnson / 123 Address ln
Record 5 - Tim Johnson / 123 Address ln
UPDATE customers a
SET address = b.address
FROM customers b
WHERE a.name = b.name
AND a.address IS NULL
AND b.address IS NOT NULL;
Assuming:
<blank address> is supposed to mean NULL
There is at most one row with address per name.
Names are actually unique identifiers - which they are not for real people names.
Else you have to be more specific.

How group by count from multiple tables

I have 3 different tables, country, city, and customer. Tables are shown below:
country table:
id country_name
1 UK
2 US
3 Brazil
:
n Canada
city table
id city_name postal_code country_id
1 London 30090 1
2 Dallas 20909 2
3 Rio 29090 3
4 Atlanta 30318 2
:
n Vancouver 32230 n
customer table
id customer_name city_id
1 John 1
2 Pete 3
3 Dave 2
4 May 2
5 Chuck 4
6 Sam 3
7 Henry 3
***country.id is references city.country_id, and city.id is references customer.city_id
I want to write a query that can extract the country name, city name and the count of the customer of the associate city. But with one condition, the query will return all cities with more customers than the average number of customers of all cities
It will look something like below, this is the correct output
UK London 2
Brazil Rio 3
but I kept getting this output, which isn't correct
UK London 2
US Dallas 2
US Atlanta 1
Brazil Rio 3
I fixed my SQL query but it doesn't give me the result that I want
SELECT country.country_name, city.city_name, COUNT(customer.city_id) from country
JOIN city on country.id = city.country_id
JOIN customer on city.id = customer.city_id
Group by city_name,country.country_name;
I am wondering how can I do this and fix my code?
add country.country_name in group by
SELECT country.country_name, city.city_name, COUNT(customer.city_id) from country
JOIN city on country.id = city.country_id
JOIN customer on city.id = customer.city_id
Group by city_name,country.country_name
You are missing country.country_name in the query it will give you error. As a general rule all columns on which aggregate function is not applied should be part of group by clause.
So either you write your query without country_name in the select or add country_name in the group by clause.

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.

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;

Track which columns were modified by an Update

How do I track the list of updated columns in a table
Table1
Name Place Email Id
John US john#gmail.com 1
Sam US sam#gmail.com 2
Now if I update Name,place columns for John and place,email for Sam like
Name Place Email Id
Johnny UK john#gmail.com 1
Sam UK sammy#gmail.com 2
I want to store the list of updated attributes in another table as following
Id ListOfModifiedAttributes Status othercolumns
1 name,place success
2 place,email success
How to achieve the above in plsql.