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;
Related
I have two tables, Table 1 with multiple columns, name, ID number, address, etc. And Table 2 with columns, ID number 1 and ID number 2 and a few other columns.
I am trying to get a T-SQL query returning all rows in Table 1 with an indicator showing whether the ID number in Table 1 matches either ID_1 or ID_2 in Table 2. The result set would be all columns from Table 1 , plus the indicator “Matched” if the ID number in Table 1 matches either ID_1 or ID_2 in Table 2.
Table 1: ID | Name | Address |
Table 2: ID_1 | ID_2
Result
T1.ID, Name, Address, ("Matched"/"Unmatched") ...
Also, would it be the same to do the opposite, meaning instead of the result including all rows from Table 1 that have a matching ID in ID_1 or ID_2 in Table 2, the result set would include only records from Table 1 where t1.ID = (T2.ID_1 or T2.ID_2)?
SELECT DISTINCT
CASE
WHEN (table1.ID = table2.ID_1 )
THEN 'Matched'
ELSE 'Unmatched'
END AS Status ,
table1.*
FROM
table1
LEFT JOIN
table2 ON table1.ID = table2.ID_1
UNION
SELECT DISTINCT
CASE
WHEN (table1.ID = table2.ID_2)
THEN 'Matched'
ELSE 'Unmatched'
END AS Status,
table1.*
FROM
table1
LEFT JOIN
table2 ON table1.ID = table2.ID_2
I think that a correlated subquery with an exists condition would be a reasonable solution:
select
t1.*,
case when exists (select 1 from table2 t2 where t1.id in (t2.id_1, t2.id_2))
then 'Matched'
else 'Unmatched'
end matched
from table1 t1
And the other way around:
select
t2.*,
case when exists (select 1 from table1 t1 where t1.id in (t2.id_1, t2.id_2))
then 'Matched'
else 'Unmatched'
end matched
from table2 t2
If you want to "align" the rows based on the match for the whole dataset at once, then you might want to try a full join:
select t1.*, t2.*
from table1 t1
full join table2 t2 on t1.id in (t2.id_1, t2.id_2)
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
I have two tables
TABLE1
skillid skillname
1 PM
2 SM
TABLE2
name skillid skillname
A 1
B 2
I want to get the skillname from table1 while inserting values into table2
Use the below query
UPDATE T2
SET T2.skillname = T1.skillname
FROM TABLE2 T2
INNER JOIN TABLE1 TI ON T1.skillid = T2.skillid
INSERT INTO Table2
SELECT #Name,
#skillid,
skillname
FROM Table1 T1
WHERE T1.skillid = #skillid
if you are using parameters to insert into table2.
I have a table structure shown below:
Id Name Sal ManagerId
1 a 5000 2
2 b 7000 3
3 c 6000 1
I need output like this
Id Name Sal Manager
1 a 5000 b
2 b 7000 c
3 c 6000 a
How can i do that?
You have to use a self-JOIN to link one table to itself:
SELECT t1.Id, t1.Name, t1.Sal, t2.ManagerName AS Manager
FROM TableName t1 INNER JOIN TableName t2
ON t1.ManagerID = t2.Id
If ManagerId is nullable you might want to use an OUTER JOIN:
SELECT t1.Id, t1.Name, t1.Sal, COALESCE(t2.ManagerName, '<no manager>') AS Manager
FROM TableName t1 LEFT OUTER JOIN TableName t2
ON t1.ManagerID = t2.Id
This should be simple enough, but somehow my brain stopped working.
I have two related tables:
Table 1:
ID (PK), Value1
Table 2:
BatchID, Table1ID (FK to Table 1 ID), Value2
Example data:
Table 1:
ID Value1
1 A
2 B
Table 2:
BatchID Table1ID Value2
1 1 100
2 1 101
3 1 102
1 2 200
2 2 201
Now, for each record in Table 1, I'd like to do a matching record on Table 2, but only the most recent one (batch ID is sequential). Result for the above example would be:
Table1.ID Table1.Value1 Table2.Value2
1 A 102
2 B 201
The problem is simple, how to limit join result with Table2. There were similar questions on SO, but can't find anything like mine. Here's one on MySQL that looks similar:
LIMITing an SQL JOIN
I'm open to any approach, although speed is still the main priority since it will be a big dataset.
WITH Latest AS (
SELECT Table1ID
,MAX(BatchID) AS BatchID
FROM Table2
GROUP BY Table1ID
)
SELECT *
FROM Table1
INNER JOIN Latest
ON Latest.Table1ID = Table1.ID
INNER JOIN Table2
ON Table2.BatchID = Latest.BatchID
SELECT id, value1, value2
FROM (
SELECT t1.id, t2.value1, t2.value2, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.BatchID DESC) AS rn
FROM table1 t1
JOIN table2 t2
ON t2.table1id = t1.id
) q
WHERE rn = 1
Try
select t1.*,t2.Value2
from(
select Table1ID,max(Value2) as Value2
from [Table 2]
group by Table1ID) t2
join [Table 1] t1 on t2.Table1ID = t1.id
Either GROUP BY or WHERE clause that filters on the most recent:
SELECT * FROM Table1 a
INNER JOIN Table2 b ON (a.id = b.Table1ID)
WHERE NOT EXISTS(
SELECT 1 FROM Table2 c WHERE c.Table1ID = a.id AND c.BatchID > b. BatchID
)