Combining two tables without losing column or rows - sql

I have two tables:
The first one has the colums "SomeValue" and "Timestamp". The other one has the columns "SomeOtherValue" and also "Timestamp".
What I need as an output is the following:
A table with the three Colums "SomeValue", "SomeOtherValue" and "Timestamp".
When a row in table 1 is like this: [2; 04/07/2017-20:05] and a row in table 2 is like that: [5; 04/07/2017-20:05], I want the combined output row to be [2; 5; 04/07/2017-20:05].
Until that point it would be easy done with a simple join, but I also need all other rows. So for example if we have a row in table 1 like [2; 04/07/2017-20:05] and no matching timestamp in table 2, the output should be like [2; ?; 04/07/2017-20:05]. The '?' stands for undefined or null. It would also be possible to not join two rows with the same timestamp but rather concating both tables, so that every row would have one empty cell with '?'.
I do realize that I didn't use correct Date/Time Format here in that example, but assume that it is used in the database.
I already tried using UNION ALL but it always removes one column.
For my use case it is not possible to query both tables independently. I really need both values in one row/object.
I hope someone can help me with this. Thank you!

What you are describing is a full outer join:
select t1.somevalue, t2.someothervalue, timestamp
from t1
full outer join t2 using (timestamp);
I don't know, however, whether SAP HANA supports the USING clause. Here is the same query with ON instead:
select
t1.somevalue,
t2.someothervalue,
coalesce(t1.timestamp, t2.timestamp) as timestamp
from t1
full outer join t2 on t2.timestamp = t1.timestamp;

Joining on a datetime stamp is not always going to be reliable unless you are setting a datetime variable and writing the value of that to both tables. It's probably not very efficient either.
That said, assuming you want all the results from table 1 and matching table 2 result if it exists then you need a left outer join
Select T1.[SomeValue]
, ISNULL(T2.[SomeOtherValue], '?')
, T1.[TimeStamp]
FROM Table1 T1
LEFT OUTER JOIN Table2 T2
ON T2.[TimeStamp] = T1.[TimeStamp]
Update based on comment from OP
If you need all rows from both tables then you could either do 2 queries as above but interchange T1 and T2 position then union the 2 queries.
SELECT T1.[TimeStamp]
, T1.[SomeValue]
, ISNULL(T2.[SomeOtherValue], '?')
FROM Table1 T1
LEFT OUTER JOIN Table2 T2
ON T2.[TimeStamp] = T2.[TimeStamp]
UNION
SELECT T2.[TimeStamp]
, T2.[SomeValue]
, ISNULL(T1.[SomeOtherValue], '?')
FROM Table2 T2
LEFT OUTER JOIN Table1 T1
ON T1.[TimeStamp] = T2.[TimeStamp]
;
Or you could insert the 1st query results into a table variable then add any missing from T2 rows into that table variable using a where not exists, then select the output.
DECLARE #TempTab TABLE
( [TimeStamp] [datetime] NOT NULL
, [SomeValue] [nvarchar] (MAX) -- or int if this is always an integer
, [SomeOtherValue] [nvarchar] (MAX) -- or int if this is always an integer
)
;
INSERT INTO #TempTab
( [TimeStamp]
, [SomeValue]
, [SomeOtherValue]
)
SELECT T1.[TimeStamp]
, T1.[SomeValue]
, ISNULL(T2.[SomeOtherValue], '?')
FROM Table1 T1
LEFT OUTER JOIN Table2 T2
ON T2.[TimeStamp] = T2.[TimeStamp]
;
INSERT INTO #TempTab
( [TimeStamp]
, [SomeValue]
, [SomeOtherValue]
)
SELECT T2.[TimeStamp]
, T2.[SomeValue]
, ISNULL(T1.[SomeOtherValue], '?')
FROM Table2 T2
LEFT OUTER JOIN Table1 T1
ON T1.[TimeStamp] = T2.[TimeStamp]
WHERE NOT EXISTS
( SELECT 1
FROM #TempTab T
WHERE T.[TimeStamp] = T2.[TimeStamp]
)
;
SELECT T.[TimeStamp]
, T.[SomeValue]
, T.[SomeOtherValue]
FROM #TempTab T
;

Related

Fectch uncommon ID between two columns

I have two tables and I need to fetch if any one ID is not present in the table 2. I tried the query but its not giving the correct result. Kindly suggest.
TABLE 1
TABLE 2
Output Should be: Because Release ID and purchase ID is not present in both the columns.
QUERY Tried :
SELECT T1_ID
FROM T1 LEFT OUTER JOIN T2
ON t1.RELEASEID=t2.RELEASEID
LEFT OUTER JOIN T2 t3
ON t1.PURCHASEID=t3.PURCHASEID
WHERE IFNULL(T2.RELEASEID,'') ='' OR IFNULL(T3.PURCHASEID,'')=''
You can use NOT EXISTS as follows:
select * from t1
where not exists (select 1 from t2
where t1.releaseid =t2.releaseid or t1.purchaseid =t2.purchaseid)
You can also use LEFT JOIN as follows:
select t1.*
from t1 left join t2
on t1.releaseid =t2.releaseid or t1.purchaseid =t2.purchaseid
where t2.t2_id is null
One method is not exists:
select t1.*
from t1
where not exists (select 1
from t2
where t2.releaseid = t1.releaseid
) and
not exists (select 1
from t2
where t2.purchaseid = t1.purchaseid
);
This should work regardless of whether ? is really a string or is supposed to represent NULL.
Note: This can take advantage of indexes on t2(releaseid) and t2(purchaseid), which can be a big boost to performance on larger data.
I think you want:
select t1.*
from table1 t1
where
(t1.release_id = '?' and t2.purchase_id = '?')
or not exists (
select 1
from table2 t2
where t1.release_id in ('?', t2.release_id)
and t1.purchase_id in ('?', t2.purchase_id)
)
If the question mark is supposed to represent null values, you can just replace all instances of = '?' with is null.
Please try this and let me know if it works.
SELECT * FROM TABLE1 WHERE NOT EXISTS (SELECT '1' FROM TABLE2 WHERE TABLE1 .RELEASEID=TABLE2.RELEASEID OR TABLE1 .PURCHASEID=TABLE2.PURCHASEID);

Unpivot without using columns names

Right now my query is resulting data in below format.
dbid askid amid
================================
d1 m1 a1
I want to change the display as
SOURCE_ID DEST_ID
========================
m1 d1
a1 d1
We can't use union all, inner joins, cross joins because in real time it is very big query and interacts with n no.of multiple tables and it already have them many no.of
I tried using unpivot but every time it is storing column names also in to rows.
Sample Query which is resulting data right now:
select DEST_ID,SOURCE_ID from
(select
t1.id as dbid,
t2.mid as askid,
t3.m2idd as amid from
table1 t1, table2 t2, table3 t3 where
t1.actid = t2.senid
and t2.denid = t2.mkid
)
unpivot INCLUDE NULLS (SOURCE_ME_GUID FOR DEST_ME_GUID IN (amid, askid));
Use UNION ALL in combination with a WITH clause.
You got confused with your join criteria somehow. I suppose either mkid or denid resides in table3. Otherwise you'd be cross joining table3. You shouldn't use this 1980s join syntax anyway; it's been made redundant in 1992 for a reason.
with ids as
(
select t1.id as dbid, t2.mid as askid, t3.m2idd as amid
from table1 t1
join table2 t2 on t2.senid = t1.actid
join table3 t3 on t3.mkid = t2.denid
)
select askid as source_id, dbid as dest_id from ids
union all
select amid as source_id, dbid as dest_id from ids;
Solution for the above issue.
select dbid as DEST_ID, SOURCE_ID
from (
select 'd1' dbid,
cast('m1' as varchar2(200)) as askid,
cast('a1' as varchar2(200)) as amid
from dual
) unpivot INCLUDE NULLS (
SOURCE_ID FOR DEST_ID IN (amid, askid)
);

Getting the value upon match from the ref table

I have 2 tables
Select distinct
ID
,ValueA
,Place (How to get the Place value from the table 2 based on the Match between 2 columns ValueA and ValueB
Here Table2 is just a ref Table I''m using)
,Getdate() as time
Into #Temp
From Table1
For example when we receive value aa in ValueA column - I want the value of "Place" = "LA"
For example when we receive value bb in ValueA column - I want the value of "Place" = "TN"
Thanks in advance!
SELECT A.ID
, A.ValueA
, B.Place
, GETDATE() INTO #TempTable
FROM Table1 A INNER JOIN Table2 B
ON A.ValueA = B.ValueB
You can do this dude:
Select ID, ValueA, Place, getdate() as Date FROM Table1 INNER JOIN Table2 on Table1.ValueA = table2.ValueB.
Hope this works dude!!!
Regards...
Select
t1.ID
,t1.ValueA
,t2.Place
,Getdate() as time
Into #Temp
From Table1 t1
inner join Table2 t2 on t1.ValueA = t2.ValueB
I believe you are looking to do an inner join:
SELECT Table1.ID, Table1.ValueA, Table2.Place
FROM Table1
INNER JOIN Table2 ON Table1.ValueA = Table2.ValueB
Assumption: ValueB on table 2 is the primary key (or at least UNIQUE and therefore a candidate key).
Also, the DISTINCT is redundant assuming that ID is a primary key. Furthermore, you more than likely do not need a temporary table since a join can be used as an inner SELECT in most databases.
The exact syntax may depend on your particular database engine.

Compare two tables, find missing rows and mismatched data

I'd like to compare two tables and get a set of results where the lookup values are mismatched as well as where the key values are missing from the other table. The first part works fine with the following query:
SELECT * FROM (
SELECT mID, mLookup
FROM m) t1
FULL OUTER JOIN (
SELECT aID, aLookup
FROM a) t2
ON t1.mID = t2.aID
WHERE
t1.mID = t2.aID AND
t1.mLookup <> t2.aLookup
However, it doesn't return rows from t1 and t2 where there is no corresponding ID in the other table (because of the ON t1.mID = t2.aID).
How can I achieve both in the same query?
Remove the ID part of the WHERE clause. The FULL OUTER JOIN ON t1.mID = t2.aID is enough to link the tables together. The FULL OUTER JOIN will return both tables in the join even if one does not have a match.
However, the WHERE t1.m_ID = t2.aID clause limits the results to IDs that exist in both tables. This effectively causes the FULL OUTER JOIN to act like an INNER JOIN.
In other words:
SELECT * FROM (
SELECT mID, mLookup
FROM m) t1
FULL OUTER JOIN (
SELECT aID, aLookup
FROM a) t2
ON t1.mID = t2.aID
WHERE
--t1.mID = t2.aID AND -- remove this line
t1.mLookup <> t2.aLookup
-- EDIT --
Re-reading your question, you wanted only the mismatches. In that case, you need to search on where either side's ID is NULL:
SELECT * FROM (
SELECT mID, mLookup
FROM m) t1
FULL OUTER JOIN (
SELECT aID, aLookup
FROM a) t2
ON t1.mID = t2.aID
WHERE
t1.mID IS NULL OR
t2.mID IS NULL OR
t1.mLookup <> t2.aLookup
The where clause of your query filters out those rows that dont have matching "Ids". Try this:
SELECT m.mId, m.mLookup, a.aId, a.aLookup
from m
full outer join a
on a.aId = m.mId
where m.mId is null
or a.aID is null
or m.mLookup <> a.aLookup
The full outer join gets all possible rows, and the where clause keeps all rows where one or the other side are null and, where they match (neither null), keeps only those rows where the "lookup" values differ.
Starting from SQL Server 2008 and also valid for Azure SQL Database, Azure SQL Data Warehouse, Parallel Data Warehouse
Following is the SQL queries;
USE [test]
GO
CREATE TABLE [dbo].[Student1](
[Id] [int] NOT NULL,
[Name] [nvarchar](256) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Student2](
[Id] [int] NOT NULL,
[Name] [nvarchar](256) NOT NULL
) ON [PRIMARY]
GO
---- You can re-run from here with your data
truncate table [Student1]
truncate table [Student2]
insert into [Student1] values (1, N'سید حیدر')
insert into [Student1] values (2, N'Syed Ali')
insert into [Student1] values (3, N'Misbah Arfin')
insert into [Student2] values (2, N'Syed Ali')
insert into [Student2] values (3, N'Misbah Arfin');
with StudentsAll (Id, [Name]) as
(
select s1.Id, s1.[Name] from Student1 s1
left outer join Student2 s2
on
s1.Id = s2.Id
),
StudentsMatched (Id, [Name]) as
(
select s1.Id, s1.[Name] from Student1 s1
inner join Student2 s2
on
s1.Id = s2.Id
)
select * from StudentsAll
except
select * from StudentsMatched

How do I compare 2 rows from the same table (SQL Server)?

I need to create a background job that processes a table looking for rows matching on a particular id with different statuses. It will store the row data in a string to compare the data against a row with a matching id.
I know the syntax to get the row data, but I have never tried comparing 2 rows from the same table before. How is it done? Would I need to use variables to store the data from each? Or some other way?
(Using SQL Server 2008)
You can join a table to itself as many times as you require, it is called a self join.
An alias is assigned to each instance of the table (as in the example below) to differentiate one from another.
SELECT a.SelfJoinTableID
FROM dbo.SelfJoinTable a
INNER JOIN dbo.SelfJoinTable b
ON a.SelfJoinTableID = b.SelfJoinTableID
INNER JOIN dbo.SelfJoinTable c
ON a.SelfJoinTableID = c.SelfJoinTableID
WHERE a.Status = 'Status to filter a'
AND b.Status = 'Status to filter b'
AND c.Status = 'Status to filter c'
OK, after 2 years it's finally time to correct the syntax:
SELECT t1.value, t2.value
FROM MyTable t1
JOIN MyTable t2
ON t1.id = t2.id
WHERE t1.id = #id
AND t1.status = #status1
AND t2.status = #status2
Some people find the following alternative syntax easier to see what is going on:
select t1.value,t2.value
from MyTable t1
inner join MyTable t2 on
t1.id = t2.id
where t1.id = #id
SELECT COUNT(*) FROM (SELECT * FROM tbl WHERE id=1 UNION SELECT * FROM tbl WHERE id=2) a
If you got two rows, they different, if one - the same.
SELECT * FROM A AS b INNER JOIN A AS c ON b.a = c.a
WHERE b.a = 'some column value'
I had a situation where I needed to compare each row of a table with the next row to it, (next here is relative to my problem specification) in the example next row is specified using the order by clause inside the row_number() function.
so I wrote this:
DECLARE #T TABLE (col1 nvarchar(50));
insert into #T VALUES ('A'),('B'),('C'),('D'),('E')
select I1.col1 Instance_One_Col, I2.col1 Instance_Two_Col from (
select col1,row_number() over (order by col1) as row_num
FROM #T
) AS I1
left join (
select col1,row_number() over (order by col1) as row_num
FROM #T
) AS I2 on I1.row_num = I2.row_num - 1
after that I can compare each row to the next one as I need