Data population - sql-server

I have a scenario like
Table1
Id. Name. Age. City
1. Aaa. 20. Ccc
2. BBB. 12. Ccc
Table 2
Id. Name. Age. City
1. FFF Ccc
Now all I need is based on the city (ccc is common in both )
I will have to change age value in table b and the expected output is
Id. Name. Age. City
1. FFF 20. Ccc
2. FFF 12. Ccc

Just Use a simple INNER JOIN :
SELECT t1.ID, t2.name, t1.Age, t1.City
FROM Table1 t1 JOIN Table2 t2 on ( t1.City = t2.City );
SQL Fiddle Demo

SELECT Table1.Id, Table2.Name, Table1.Age, Table1.City
FROM Table1
INNER JOIN Table2
ON Table1.City=Table2.City
It's easier if you tabulate the table name and the values in your question.
(use code block)

Related

Sqlserver minus with unmatched columns

I have two tables with different columns and want intersect records.
Table1:
Id name age
1 AAA 20
2 AAA 30
3 BBB 25
4 BBB 30
Table2:
name age
AAA 20
BBB 30
Expect Output:(Table2 - Table1)
Id name age
2 AAA 30
3 BBB 25
You can use NOT EXISTS with a correlated subquery to check that no tuple (name, age) with identical values exists.
SELECT *
FROM table1 t1
WHERE NOT EXISTS (SELECT *
FROM table2 t2
WHERE t2.name = t1.name
AND t2.age = t1.age);
Use Right Join
SELECT DISTINCT Table1.Id, Table1.Name, Table1.Age
FROM Table2 RIGHT JOIN Table1 ON Table1.Name = Table2.Name AND Table1.Age = Table2.Age
WHERE Table2.Name IS NULL
FIDDLE DEMO

SQL Server join two columns both ID of a table with another table's primary Key Column

I was wondering if there is an easy way of joining these two tables.
Table1
Name FromCountryID ToCountryID
------------------------------
sam 1 2
lee 3 4
john 2 1
Table2:
CountryID CountryName
1 USA
2 UK
3 Canada
4 Nepal
You need to join the same table twice with different alias names
select t1.name,
fromTab.countryName as FromCountry,
toTab.countryName as ToCountry
from table1 t1
left join table2 fromTab on fromTab.countryId = t1.fromCountryId
left join table2 toTab on toTab.countryId = t1.toCountryId
SELECT * FROM Table1 INNER JOIN Table2 ON Table2.CountryID = Table1.FromCountryID

Stored Proc to insert rows using Joins

I have 2 tables having IP_Address as common column. My requirement is to get the IP_Address and its associated details in table 1 that are for last 90 days and are not in table 2 and insert the delta in a new table on an nightly basis
DB used: oracle 11g
Table 3 should contain 1 record per IP_Address from Table 1 that are not in Table 2
Table 1
--------------------------------------------------
IP_Address Store_name source TRANS_INIT_TIME
--------------------------------------------------
192.168.0.1 abc e 16-06-29 05:49:16.775265000
192.168.0.1 abc e 16-07-01 07:44:29.019723000
192.168.0.2 ghi b 16-07-06 10:53:54.588610000
192.168.0.2 ghi b 16-07-12 04:04:20.293644000
192.168.0.3 hjg e 16-07-12 03:54:36.024915000
192.168.0.3 hjg e 16-07-15 03:46:27.712961000
192.168.0.4 uiu e 16-09-12 08:57:48.360136000
Table 2
--------------------------
IP.Address loc name
--------------------------
192.168.0.2 hjh uiui
Table 3
--------------------------------
IP_Address Store_name source
-------------------------------
I have prepared join to get the unique IP_Address from table1.
SELECT DISTINCT T1.IP_ADDRESS
FROM Table1 T1
LEFT JOIN TABLE2 T2
ON T1.IP_ADDRESS= T2.IP_ADDRESS
WHERE T1.TRANS_INIT_TIME BETWEEN SYSDATE-90 AND SYSDATE
AND T2.IP_ADDRESS IS NULL
AND T1.IP_ADDRESS IS NOT NULL;
I am struck here on how to get the first row data for these returns IPs and insert them in table 3 through procedure. can anyone help no this ?
Expected Result:
Table 3
--------------------------------
IP_Address Store_name source
-------------------------------
192.168.0.1 abc e
192.168.0.2 ghi b
192.168.0.3 hjg e
192.168.0.4 uiu e
In your case is enough test only the left join key column that is null (this mean that this key don't match with the key form the main table
and for insert you can use an insert select
INSERT INTO Table3 (IP_ADDRESS, Store_name, source)
SELECT DISTINCT T1.IP_ADDRESS, min(T1.Store_name), min(T1.Source)
FROM Table1 T1
LEFT JOIN TABLE2 T2
ON T1.IP_ADDRESS= T2.IP_ADDRESS
WHERE T1.TRANS_INIT_TIME BETWEEN SYSDATE-90 AND SYSDATE
and AND T2.IP_ADDRESS IS NULL
group by T1.IP_ADDRESS
You want the IP_ADDRESS to be unique in the result set but you haven't indicated which row you want for store_name and source. Just pick one randomly maybe? I'm not sure which one you want but here are three different ways to get that table3 you want.
Using an aggregate so you can group by IP_ADDRESS and correlated subquery:
SELECT T1.IP_ADDRESS, MAX(T1.STORE_NAME) AS STORE_NAME, MAX(T1.SOURCE) AS SOURCE
FROM Table1 T1
WHERE NOT EXISTS (SELECT NULL
FROM TABLE2 T2
WHERE T1.IP_ADDRESS = T2.IP_ADDRESS)
GROUP BY T1.IP_ADDRESS
ORDER BY T1.IP_ADDRESS;
Using an aggregate and a left outer join:
SELECT T1.IP_ADDRESS, MAX(T1.STORE_NAME) AS STORE_NAME, MAX(T1.SOURCE) AS SOURCE
FROM Table1 T1
LEFT OUTER JOIN TABLE2 T2 ON T1.IP_ADDRESS = T2.IP_ADDRESS
WHERE T2.IP_ADDRESS IS NULL
GROUP BY T1.IP_ADDRESS
ORDER BY T1.IP_ADDRESS;
Using an analytical function and correlated subquery:
SELECT SUB.IP_ADDRESS, SUB.STORE_NAME, SUB.SOURCE
FROM (
SELECT T1.IP_ADDRESS, T1.STORE_NAME, T1.SOURCE, ROW_NUMBER() OVER (PARTITION BY T1.IP_ADDRESS) AS ROWNUMBER
FROM Table1 T1
WHERE NOT EXISTS (SELECT NULL
FROM TABLE2 T2
WHERE T1.IP_ADDRESS = T2.IP_ADDRESS)
) AS SUB
WHERE SUB.ROWNUMBER = 1
ORDER BY SUB.IP_ADDRESS;

SQL Server 2008 - Fill the blank value

I am having a problem write a query that fill in the blank value. I know it sounds confusing so let me demonstrate and explain.
Says, I have a query "Select Name, Serial, TrackNum From Table1" and the result is below:
Table1
Name Serial TrackNum
AAA
AAA 222 T1
BBB 333 T1
BBB 444 T2
BBB 555
BBB 666
CCC 777 T3
CCC 888
CCC 999
DDD 998
EEE 997 T4
EEE 996
FFF T5
I am having problem to form a query to produce this result below. You see that Serial# 555 and 666 were inherited "T2" from the row above, and same thing for Serial# 888 and 999. However, part# DDD has serial but not track#. And FFF has not serial but track#.
Name Serial TrackNum
AAA
AAA 222 T1
BBB 333 T1
BBB 444 T2
BBB 555 T2
BBB 666 T2
CCC 777 T3
CCC 888 T3
CCC 999 T3
DDD 998
EEE 997 T4
EEE 996 T4
FFF T5
Please help and appreciate if you provide sample code.
Would this work for your needs? The caveat to this technique is that the first row for AAA will also display T1 for the TrackNum rather than an empty string/NULL.
DECLARE #Table1 TABLE (Name VARCHAR(3),Serial VARCHAR(3),TrackNum VARCHAR(3))
INSERT #Table1
VALUES ('AAA','','')
,('AAA','222','T1')
,('BBB','333','T1')
,('BBB','444','T2')
,('BBB','555','')
,('BBB','666','')
,('CCC','777','T3')
,('CCC','888','')
,('CCC','999','')
;WITH c AS (SELECT Name,
MAX(TrackNum) AS TrackNum
FROM #Table1
GROUP BY Name)
SELECT t.Name, t.Serial, CASE
WHEN t.TrackNum IS NULL OR t.TrackNum = ''
THEN CASE
WHEN t.Serial IS NULL OR t.Serial = ''
THEN ''
ELSE c.TrackNum
END
ELSE t.TrackNum
END AS TrackNum
FROM #Table1 t
JOIN c ON t.Name = c.Name
If you want to UPDATE anything this can give you an idea.
;WITH c AS (SELECT Name,
MAX(TrackNum) AS TrackNum
FROM #Table1
GROUP BY Name)
UPDATE t
SET t.TrackNum = c.TrackNum
FROM #Table1 t
JOIN c ON t.Name = c.Name
WHERE t.TrackNum IS NULL OR t.TrackNum = ''
SELECT *
FROM #Table1
Assuming those are NULL values:
SELECT Name, Serial,
CAST(
SUBSTRING(
MAX( CAST(Name AS BINARY(4)) + CAST(Serial AS BINARY(4)) )
OVER( ORDER BY Name
ROWS UNBOUNDED PRECEDING ),
5, 4)
AS varchar(5)) AS TrackNum
FROM table
Courtesy of Mr. Ben-Gan, http://sqlmag.com/t-sql/last-non-null-puzzle

SQL joins vs subqueries vs exists for matching and filtering rows

I have a table which has the following fields : Id, Name, Dept
Sample data :
ID Name Dept
1 John A
2 Mary A
3 Tom A
4 David A
5 Mary B
6 David B
I am trying to get the names which are in Dept'A' but NOT in Dept'B'
I was able to come up with a query which gives the desired results :
select Id, Name, Dept
from test
Where Dept= 'a' and name not in (
select name from test where Dept= 'b')
But how can I do the same with joins?
You can use LEFT JOIN:
SELECT t1.*
FROM test t1
LEFT JOIN test t2
ON t1.Name = t2.Name
AND t2.Dept = 'B'
WHERE
t1.Dept = 'A'
AND t2.ID IS NULL
But I prefer the NOT EXISTS approach:
SELECT *
FROM test t
WHERE
t.Dept = 'A'
AND NOT EXISTS(SELECT 1 FROM test WHERE Name = t.Name AND Dept = 'B')
Aaron Bertrand wrote an article comparing the different techniques to check for existence of a row, with NOT EXISTS typically being the best choice.
Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
How about:
SELECT A.Id, A.Name, A.Dept
FROM test A, test B
WHERE A.Dept= 'a'
AND B.Dept = 'b'
AND A.Name <> B.Name

Resources