Simple nested query on the same table - sql

So this is my table set up of 100k rows. I have around 30k rows which have the wrong dealer associated to it even though it refers to the same person but just a different bank designation. This happened due to a failure to port information accurately from a previous version of the database .
Table CustomerName
Name Bank Dealer SSN
John 1 ABC unique1
Mike 1 DEF unique2
Mike 2 wrong unique2
Mark 1 XYZ unique3
Mark 2 wrong unique3
Desired Table set up
Table CustomerName
Name Bank Dealer SSN
John 1 ABC unique1
Mike 1 DEF unique2
Mike 2 DEF unique2
Mark 1 XYZ unique3
Mark 2 XYZ unique3
I want to write a query which will target the rows (Bank 2 rows essentially) and change it to Bank 1 Dealer values. Is there a way to do it ? I'm using T-SQL ( SSMS 2016 )
EDIT :
SSN are like primary keys for the customer. every customer will have one ssn . the bank 2 is basically a delinquent account bank. A customer may or may not have a bank 2 account , but they'll have a bank 1 account. But my problem is that somehow the dealer didn't come through right for bank 2 and I need to update to the correct value

The question is which Dealer to use. Let me guess that it is the first one. You can use CTE and update to accomplish this:
with topudate as (
select cn.*,
max(case when bank = 1 then dealer end) over (partition by ssn) as dealer1
from customername cn
)
update toupdate
set dealer = dealer1
where dealer <> dealer1 or dealer is null;
If you have some other logic for getting the right name, then that would go in the case expression instead.

update bank2
set bank2.dealer = bank1.dealer
from CustomerName bank1
join CustomerName bank2
on bank2.SSN = bank1.SSN
and bank2.Bank = 2
and bank1.Bank = 1

Related

Find rows for an id where value changes in any of the coloumn in sql

I have a table with say 10 columns where the unique identifier is id column.
I need print all the rows where value for any given id changes for any of the 10 coloums.
Eg:
Id name city state address mail phn number store no business name date
1 adam california ca acbb street xyz#gmail.com 12345 456 abc pvt 01-01-2017
1 adam newyork Ny avc xyz#gmail.com 12345 456 abc pvt 11-03-2018
1 adam newyork Ny avc xyz#gmail.com 12345 456 abcd pvt 24-03-2018
2 brian dallas Tx sasa sasa#gmail.com 21212 dsdssd ltd 01-01-2017
2 brian dallas Tx sasa sasa#gmail.com 232323 21212 dsdssd ltd 01-01-2017
3 donald dallas Tx qwer qwwqw#gmail.com 2121212 435345 sffsss ltd 23-01-2017
As shown above for id 1 there is a change from the first row to 2nd row on city state address so that should come .also for id 1 the 3rd row changes only business name so that should also be printed.
So basically for an id the status for that id before that date should be checked and if there is any change in any column it should be printed.
Same goes for id 2.For id 3 there is only one entry so that should not be printed.
The check needs to be done based on date for an id.
The data set that I have is in millions so would need a fine tuned query.
If you have a column for row number( for example ROWID), you can simply select all rows that has a pair (based on ID) in previous records and check if any of the last row columns differs from the first one:
select a.* from [yourTable] a
inner join [yourTable] b
on a.Id = b.Id where a.RowId > b.RowId
and (a.name <> b.name OR a.city <> b.city OR a.state <> b.state OR a.address <> b.address ... )

Normalize data with index from table

I have a table (call it tblContractor) like so: (first row in intentionally empty):
ContractorId ContractorName LicenseNumber
0
1 Smith Inc A12345
43 Joe's LLC B4C5t6
4 SureFix Co. 77987
77 ReadyMix 009ABCV
and a table tblProject like so:
ProjectId Name ContractorName ContractorId
32 SureFix Co. NULL
40 Joe's LLC NULL
42 ReadyMix NULL
44 Smith Inc NULL
I've just created that last column, ContractorId, because I want to normalize the data,
i.e. have the ContractorName in only tblContractor and an index to the Contractor in tblProject.
So tblProject will look like:
ProjectId Name ContractorName ContractorId
32 SureFix Co 77987
40 Joe's LLC B4C5t6
42 ReadyMix 009ABCV
44 Smith Inc A12345
How do I do this?
This is what I've go so far but it doesn't work:
SELECT project.ProjectId, project.Name, project.ContractorName, project.ContractorId
FROM tblProject project
WHERE NOT EXISTS (
SELECT TOP 1 *
FROM tblContractor contractor
WHERE project.ContractorName = contractor.ContractorName)
Order by ContractorName
Sorry for the table formatting. I looked at the questions about table formatting for SO questions and I guess there really isn't a good way to do it.
Try starting with this to get the contractorid data moved over:
update a set a.contractorid=b.contractorid from tblProject a
join tblContractor b on a.name=b.name

select rows with non distinct values in column 1 scoped to column 2

So i have a people table and bank_accounts table:
People
id | name
1 John
2 Mark
3 Mary
BankAccount
id | person_id | currency
1 1 'USD'
2 1 'EUR'
3 2 'USD'
4 2 'USD'
5 3 'EUR'
I want to get back all accounts with their owners if that owner has only accounts with max one kind of currency. I don't want to get back any account which is owned by user which has another account in another currency. erm :P
so the table i want to get back looks like that:
account_id | person_id | currency
3 2(Mark) 'USD'
4 2(Mark) 'USD'
5 3(Mary) 'EUR'
Hope it's understandable. This is simplified example of course. I will use this on a lot bigger tables with a lot of data. So some efficiency would be also good.
Thanks a lot for your time and help!
select *
from bankAccount
where person_id in
(
select person_id
from bankAccount
group by person_id
having count(distinct currency) = 1
)

Concatenating data from one row into the results from another

I have a SQL Server database of orders I'm struggling with. For a normal order a single table provides the following results:
Orders:
ID Customer Shipdate Order ID
-----------------------------------------------------------------
1 Tom 2015-01-01 100
2 Bob 2014-03-20 200
At some point they needed orders that were placed by more than one customer. So they created a row for each customer and split the record over multiple rows.
Orders:
ID Customer Shipdate Order ID
-----------------------------------------------------------------
1 Tom 2015-01-01 100
2 Bob 2014-03-20 200
3 John
4 Dan
5 2014-05-10 300
So there is another table I can join on to make sense of this which relates the three rows which are actually one order.
Joint.Orders:
ID Related ID
-----------------------------------------------------------------
5 3
5 4
I'm a little new to SQL and while I can join on the other table and filter to only get the data relating to Order ID 300, but what I'd really like is to concatenate the customers, but after searching for a while I can't see how to do this. What'd I'd really like to achieve is this as an output:
ID Customer Shipdate Order ID
----------------------------------------------------------------
1 Tom 2015-01-01 100
2 Bob 2014-03-20 200
5 John, Dan 2014-05-10 300
You should consider changing the schema first. The below query might help you get a feel of how it can be done with your current design.
Select * From Orders Where IsNull(Customer, '') <> ''
Union All
Select ID,
Customer = (Select Customer + ',' From Orders OI Where OI.ID (Select RelatedID from JointOrders JO Where JO.ID = O.ID)
,ShipDate, OrderID
From Orders O Where IsNull(O.Customer, '') = ''

How to insert a record in a table so that the string field with id?

I have a table to be imported from excel.It has an column called the sector table name "ExcelTable"
Name Title Sector
John manager Sofware
Sam Lawyer Jus
"ExcelTable" has 3284 rows.I create table called "SECTORS"."SECTORS" table's cloumn like this
SectorId SectorName
1 Sofware
2 Jus
It has 61 rows.
I inserted "EXCELTABLE" to "GLOBALCONTACTS".They has same rows number 3284 I want to insert "GLOBAL_CONTACTS" table sector by sectorid .It is now
ContactId Name Title Sector
1 John manager null
2 Sam Lawyer null
I want it to be like this
ContactId Name Title Sector
1 John manager 1
2 Sam Lawyer 2
I think you just want to join ExcelTable to Sectors for an INSERT:
INSERT INTO GLOBAL_CONTACTS (Name,Title,Sector)
SELECT e.Name,e.Title,s.SectorID
FROM ExcelTable e
INNER JOIN Sectors s
ON e.Sector = s.SectorName