Unable join columns side by side from from different tables - sql

I have two tables. Let's call it as t1 and t2. Below is the t1 table
t1(product_number, date, sales_before)
t2(product_number, date, sales_after)
t1 table contains 247 rows and t2 contains 264 rows. I'm trying to match the rows on product_number and date and did inner join.
select t1.*, t2.sales_after from t1
inner join t2
on t1.product_number = t2.product_number
and t1.date = t2.date
But it's returning around 600 rows.
The t1 and t2 table samples are below
t1
product_number date sales_before
1 2022-01-01 22
2 2022-01-02 20
3 2022-01-03 47
t2
product_number date sales_after
1 2022-01-01 31
2 2022-01-02 9
4 2022-01-10 97
I'm expecting output like
product_number date sales_before sales_after
1 2022-01-01 22 31
2 2022-01-02 20 9
3 2022-01-03 47 NULL
4 2022-01-10 NULL 97
Can anyone help me with this?

Try this code
enter code here
SELECT COALESCE(t2.product_number,t1.product_number) product_number
,COALESCE(t1.date,t2.date)date ,
t1.sales_before ,
t2.sales_before
FROM #t1 t1
full JOIN #t2 t2 ON t1.product_number = t2.product_number
AND t1.date = t2.date

try it :
SELECT COALESCE(t2.product_number,t1.product_number) product_number
,COALESCE(t1.date,t2.date)date ,
t1.sales_before ,
t2.sales_after
FROM t1
full outer JOIN t2 ON t1.product_number = t2.product_number
AND t1.date = t2.date

Wha i've done here is I've added coalesce and fuller join inplace of inner join. Below is the query
select
coalesce(t1.product_number, t2.product_number),
coalesce(t2.date, t2.date),
t1.sales_before,
t2.sales_after
from
t1
full outer join t2 on t1.product_number = t2.product_number
and t1.date = t2.date

Related

In Bigquery: How to pick max(date) row while performing full outer join in case of duplicates?

I'm performing full outer join to combine two tables in bigquery in order to get all rows and columns from both the tables.
select distinct t1.Org,t1.begindate,t1.enddate,<fetch unit based on enddate> as f_Unit
from table1 t1
full outer join table2 t2
on t1.Org = t2.Org
Now the problem here is, both the tables have some rows with same value for all columns except enddate and Unit column
table1
Org Store Product begindate enddate FalUnit
01 12 xx 2020-04-16 9999-12-31 5
01 13 yy 2011-03-23 null 0
table2
Org Store Product begindate enddate Unit
01 12 xx null null 1
01 14 zz null null 3
in that case have to pick up the max(enddate) and it's respective Unit as well.
Output_Table
Org Store Product begindate enddate FalUnit Unit f_Unit
01 12 xx 2020-04-16 9999-12-31 5 null 5
01 13 yy 2011-03-23 null 0 null 0
01 14 zz null null null 3 3
How to include this condition to this query or any other approach possible other than joins ?
Any help will be appreciated to solve this issue.
Hmmm . . . I am thinking a prioritization. Something like this:
select t1.*
from table1 t1
union all
select t2.*
from table2 t2
where not exists (select 1
from table1 t1
where t1.org = t2.org and t1.store = t2.store and t1.product = t2.product
);
At the very least, this will return your specified results for the specified data in the question.

MSSQL get rows which only differ at 2 columns

I have a task on which I have no idea how that could even work out.
I have to find records, which have a time difference of X and where a boolean is ON/OFF. I tried to use a LEFT OUTER JOIN and used the conditions in the ON clause, but it gave me the wrong result.
So my question is, how can I select rows, which have the same value in 2 columns, but different values in other 2 columns?
Edit:
My problem is, that for some reason my actual query returns the same entry multiple times. I checked if the entry exists multiple times, but it doesn't
Data for reference:
ID1 ID2 Boolean Time
1 1 0 2018-03-06 11:31:39
1 1 1 2018-03-06 11:33:39
2 1 0 2018-03-06 11:31:39
2 2 1 2018-03-06 11:40:39
The desired output from the query would be
ID1 ID2 Boolean Time
1 1 0 2018-03-06 11:31:39
1 1 1 2018-03-06 11:33:39
because ID1 and ID2 are the same, the Boolean is different and the time difference is in the specified range (lets say 5 minutes). The other 2 entries are not valid, because ID2 differs and the time difference is too big.
My current query:
select
t1.id1,
t1.id2,
t1.boolean,
t1.time
from t1 t1
left outer join t1 t2
on t1.boolean != t2.boolean and datediff(minute, t1.time, t2.time)<=5
where t1.id1 = t2.id1
and t1.id2 = t2.id2
Your query looks fine, I found few small issues
1- Table alias used is wrong instead of t it should be t1
2- Order or data is wrong
3- Changed left join to inner join
4- Modified ON and Where condition for better readability and performance
Check following corrected query.
WITH t1 AS
(
SELECT * FROM (VALUES
(1 , 1 , 0 , '2018-03-06 11:31:39'),
(1 , 1 , 1 , '2018-03-06 11:33:39'),
(2 , 1 , 0 , '2018-03-06 11:31:39'),
(2 , 2 , 1 , '2018-03-06 11:40:39')
) T( ID1, ID2 , Boolean, Time)
)
select
t1.id1,
t1.id2,
t1.boolean,
t1.time
from t1 t1
inner join t1 t2
on t1.id1 = t2.id1 and t1.id2 = t2.id2
where
t1.boolean != t2.boolean and datediff(minute, t1.time, t2.time)<=5
ORDER BY [TIME]
Output
+-----+-----+---------+---------------------+
| id1 | id2 | boolean | time |
+-----+-----+---------+---------------------+
| 1 | 1 | 0 | 2018-03-06 11:31:39 |
+-----+-----+---------+---------------------+
| 1 | 1 | 1 | 2018-03-06 11:33:39 |
+-----+-----+---------+---------------------+
To avoid duplicate value use GROUP BY
SELECT t1.id1
,t1.id2
,t1.boolean
,t1.TIME
FROM t1 t1
INNER JOIN t1 t2 ON t1.boolean != t2.boolean
AND datediff(minute, t1.TIME, t2.TIME) <= 5
WHERE t1.id1 = t2.id1
AND t1.id2 = t2.id2
GROUP BY t1.id1
,t1.id2
,t1.boolean
,t1.TIME
SELECT
D1.*
FROM
Data AS D1
WHERE
EXISTS (
SELECT
1
FROM
Data AS D2
WHERE
D1.ID1 = D2.ID2 AND
~D1.Boolean = D2.Boolean AND
ABS(DATEDIFF(MINUTE, D1.Time, D2.Time)) <= 5)
ORDER BY
D1.ID1,
D1.Boolean,
D1.Time

Sql query to get join of two tables and both table has where query

Stuck at join, tried left, right, left outer , right outer joins
table 1
selectionID name type
1 abc 1
2 def 1
3 ghi 2
4 dhi 2
5 gki 2
6 ppp 2
Table 2
TID UserID selectionID isOK
1 10 3 0
2 19 3 0
3 10 8 0
6 10 5 1
Desired result is
join of
select from table 1 where type =2
select from table 2 where UserID = 10
selectionID name type TID userID
3 ghi 2 1 10
4 dhi 2 undefined undefined/null
5 gki 2 undefined undefined/null
6 ppp 2 6 10
so basically i want all data from table 1 that fits in where clause and their respective data in table 2 with another where clause
As long as i have done research i need to use inner query of second table...am I going right way?
Try the following query:
SELECT t1.selectionID, t1.name, t1.type, t2.tid, t2.userID
FROM table1 t1 LEFT JOIN table2 t2 ON t1.type = t2.TID AND t2.userID = 10
WHERE t1.type = 2;
Stuck at join, tried left, right, left outer , right outer joins ... well LEFT JOIN is same as LEFT OUTER JOIN. BTW, you are looking for a LEFT JOIN probably like
select t1.selectionID,
t1.name,
t1.type,
t2.TID,
t2.UserId
from table1 t1
left join table2 t2 on t1.selectionID = t2.selectionID
and t2.UserId = 10
where t1.type = 2;
You were probably failing because placing the conditions in the where clause. If a row doesn't join you will have nulls in its columns, so a where condition will discard those rows
select *
from table1 t1
left join
table2 t2
on t1.selectionID = t2.selectionID and
t2.userID = 10
where t1.type = 2
Another way, is to force nulled rows to be accepted, using coalesce
select *
from table1 t1
left join
table2 t2
on t1.selectionID = t2.selectionID and
where t1.type = 2 and
coalesce(t2.userID, 10) = 10
select * from table1 t1
left join table2 t2 ON t1.SelectionID = t2.SelectionID
where t1.type = 2 AND t2.UserID = 10

Waterfall join conditions

I have two tables similar to:
Table 1 --unique ID's
ID Date
1 3/8/2017
2 3/8/2017
3 3/8/2017
Table 2
ID Date SourceID
1 3/8/2017 1
1 3/8/2017 2
1 3/8/2017 3
2 3/8/2017 2
3 3/8/2017 1
3 3/8/2017 3
And I want to write a query that has a result like:
Result
ID SourceID
1 2
2 2
3 1
Where the source ID ordering should be 2, 1, 3
I have:
select Table1.ID
, COALESCE(Join1.SourceID, Join2.SourceID, Join3.SourceID) as SourceID
from Table1
left outer join Table2 Join1
on Table1.date = Join1.date
and Table1.ID = Join1.ID
and Join1.SourceID = 2
left outer join Table2 Join2
on Table1.date = Join2.date
and Table1.ID = Join2.ID
and Join2.SourceID = 1
and Join1.SourceID is null
left outer join Table2 Join3
on Table1.date = Join3.date
and Table1.ID = Join3.ID
and Join3.SourceID = 3
and Join1.SourceID is null
and Join2.SourceID is null
But this currently just keeps the records where sourceid = 2 and does not add in the other sourceid's.
Thanks in advance for any help. Let me know if you need any clarification. Using SQL-Server. I only need a few and fixed amount of sources so I am avoiding using a cursor.
This is a prioritization query. I would do it using outer apply:
select t1.*, t2.sourceId
from table1 t1 outer apply
(select top 1 t2.*
from table2 t2
where t2.id = t1.id and t2.date = t1.date
order by (case t2.sourceid when 2 then 1 when 1 then 2 when 3 then 3 end)
) t2;
Note: For readability, you can simplify the order by to:
order by charindex(cast(t2.sourceId as varchar(255)), '2,1,3')
If you are uncomfortable with outer apply, you can do the same thing with a single join:
select t1.*, t2.sourceId
from table1 t1 join
(select t2.*,
row_number() over (partition by id, date
order by (case t2.sourceid when 2 then 1 when 1 then 2 when 3 then 3 end)
) as seqnum
from table2 t2
) t2
on t2.id = t1.id and t2.date = t1.date and t2.seqnum = 1;

SQL subtract times from tables (decreased additionally for specific time status from second table)

I have table T1 and T2.
T1
ID TIME1 TIME2
1001 1 10
1002 1 20
T2
ID STATUS TIME
1001 NEW 1
1001 CLOSED 10
1002 NEW 1
1002 HOLD 5
1002 CLOSED 13
I want result TIME2-TIME1 if status HOLD does not exist in table T2; or TIME2-TIME1-TIME if status HOLD exist in table for that record
1001 9 (10-1)
1002 14(20-1-5)
I initially wrote SQL query but this does not work because it returns NULL for first record while the for the second record result is OK
SELECT T1.ID,T1.TIME2-T1.TIME1-T2.TIME
FROM T1
LEFT OUTER JOIN T2 ON T1.ID=T2.ID AND T2.STATUS='HOLD'
Thanks
or in short
select
t1.id,
t1.time2-case when status='HOLD' then t2.time else 0 end-t1.time1
from
t1 left join t2 on t1.id=t2.id and t2.status='HOLD'
SELECT T1.ID
, Case
When T2.STATUS = 'HOLD' THEN T1.Time2 - T1.Time1 - T2.Time
Else T1.Time2 -T1.Time1
END
FROM T1
LEFT OUTER JOIN T2 ON T1.ID=T2.ID AND T2.STATUS='HOLD'
Evidently table T2 may contain more than one row matching T1.ID. Assuming that T2 always contains at least one such row, then we can do:
select T1.ID, min(case when T2.STATUS<>'HOLD' then T1.TIME2-T1.TIME1
when T2.STATUS='HOLD' then T1.TIME2-T1.TIME1-T2.[TIME] end)
from T1 join T2
on T1.ID=T2.ID
group by T1.ID