SQL Join on partial column data (SQL Server) - sql

Both columns are tinyint if it matters.
Table1
Version
--------
111115
222226
333337
Table2
ID Year
--------
5 2015
6 2016
7 2017
I need to join on the ID from table 2 if it equals the last value in the version field from table 1.
Version 111115 would join to ID 5. I know how to select on things like this but is joining feasible? The result being:
111115 5 2015
TIA!

You can use the RIGHT() function to do this:
SELECT *
FROM Table1 A
INNER JOIN Table2 B on RIGHT(A.Version,1) = B.ID
I would probably avoid having to do this very much though. It is a faulty database design. Perhaps add a column ID to table 1, and use:
UPDATE Table1
SET ID = RIGHT(Version,1)

Since they are both integer, you can try the modulus operator. It takes the remainder after division. So 111115 % 10 is 5.
SELECT *
FROM Table1 t1
INNER JOIN Table2 t2 on t1.Version % 10 = t2.ID

Declare #tblTest as table
(
id INT,
yearName INT
)
Declare #tblVersion as table
(
VersionNo INT
)
INSERT INTO #tblTest values(5,2015)
INSERT INTO #tblTest values(6,2016)
INSERT INTO #tblTest values(7,2017)
INSERT INTO #tblVersion values(111115)
INSERT INTO #tblVersion values(111116)
INSERT INTO #tblVersion values(111117)
select
*,RIGHT(VersionNo,1)
from #tblVersion
SELECT
*
FROM #tblTest T1
LEFT JOIN (SELECT RIGHT(VersionNo,1) AS VersionId,VersionNo FROM #tblVersion) T2 ON T2.VersionId=T1.id

Related

How do i count occurences that were joined SQL

I am joining two tables:
DECLARE #Temp TABLE (
id INT)
INSERT INTO #Temp
VALUES (5)
,(2)
,(3)
DECLARE #Temp2 TABLE (
member_id INT)
INSERT INTO #Temp2
VALUES (5)
,(1)
,(3)
How do i count the number of rows that can be LEFT joined and the ones that can't.
In this example: 5 & 3 from #Temp can be joined to #Temp2 and only 2 from #Temp can't be joined.
I would like my output to show the following:
+--------+------------+
| Joined | Not_Joined |
+--------+------------+
| 2 | 1 |
+--------+------------+
You can do this in a single query using COUNT and SUM. This should produce the results you are looking for.
DECLARE #Temp TABLE (
id INT)
INSERT INTO #Temp
VALUES (5)
,(2)
,(3)
DECLARE #Temp2 TABLE (
member_id INT)
INSERT INTO #Temp2
VALUES (5)
,(1)
,(3)
select Joined = count(t2.Member_id)
, NotJoined = sum(case when t2.Member_id is null then 1 end)
from #Temp t
left join #Temp2 t2 on t2.member_id = t.id
The count from #Temp that EXISTS in #Temp2:
SELECT COUNT(*) FROM #TEMP WHERE ID IN(SELECT MEMBER_ID FROM #TEMP2)
The count from #Temp2 not in #Temp:
SELECT COUNT(*) FROM #TEMP2 WHERE MEMBER_ID NOT IN(ID FROM #TEMP)
Now to create a single result set, there are many ways but here is a simple one:
SELECT
(SELECT COUNT(*) FROM #TEMP2 WHERE MEMBER_ID IN(ID FROM #TEMP)) AS [Joined],
(SELECT COUNT(*) FROM #TEMP WHERE ID NOT IN(SELECT MEMBER_ID FROM #TEMP2)) AS [NotJoined]
#Sean Lange's answer is more specific to the JOIN question, my answer simply counts what exists in the lists.
Select count(*) as 'NOT Joined ',
(Select t1.count(*) from table1
t1)-count(*) as 'Joined'
from table1 where id NOT IN (Select member_id from table2);
Its basically how a left join works that is Common values of both the
tables plus the value of table 1 which doesnt exists in table 2.

SQL Inner join and Not in

I am trying to run a query and not sure why the returned record set is off by 60 rows.
Select t1.* into #temp1
from NameExt as t1
join #temp1 as t2
on t1.AN = t2.AN --164172
Select t1.* into #temp3
from NameExt as t1
where AN in (Select AN from #temp1) --164112
When I do an intersect or except on #temp1 and #temp2, I dont get any rows back.
Really need to understand why the two queries are returning not a similar record set.
Even this returns the same number of rows as the 2nd query
Select * into #temp3 from NameExt as t1 where exists
( Select 1 from #temp1 as t2 where t1.AN = t2.AN) --164112
Thanks much
You can easily see what values are causing problems by doing:
select t2.AN
from #temp1 t2
group by t2.AN
having count(*) > 1;
Duplicates in the second table are causing the problem. You know how to fix it . . . using in or exists.
Your query is incorrect. You cannot select from and create a temp table at the same time..
Select t1.* into #temp1
from NameExt as t1
join #temp1 as t2
on t1.AN = t2.AN --164172
As per a comment, you likely have multiple rows in #temp1 with the same value in AN...
CREATE TABLE x (
id INT
)
CREATE TABLE y (
id INT,
x_id INT
)
INSERT INTO x VALUES (1), (2), (3)
INSERT INTO y VALUES (1, 2), (2, 2), (3, 3)
SELECT *
FROM x INNER JOIN y ON x.id = y.x_id
-- a total of three rows
-- x.id | y.id | y.x_id
------------------------
-- 2 | 1 | 2
-- 2 | 2 | 2
-- 3 | 3 | 3
SELECT *
FROM x
WHERE x.id IN (SELECT y.x_id FROM y)
-- a total of two rows
-- x.id
--------
-- 2
-- 3
http://sqlfiddle.com/#!18/7e1d1/2

Update table value by adding from other table

Can you please help me out with the below issue?
I have a table like below.
Table-1
Sales_RepID-- Name-- Products_Count
1-- ABC-- 2
2-- XYZ-- 4
3-- XXX-- 3
Table-2
Order_ID-- Sales_RepID-- Products_Count
1001-- 2 -- 2
1002-- 1 -- 1
1003-- 2 -- 1
1004-- 3 -- 3
1005-- 2 -- 2
Table - 1 Result
Sales_RepID, --Name, --Products_Count
1-- ABC --3
2-- XYZ --9
3-- XXX --6
I want to add table-2 Products_Count to Table-1 Products_Count for each Sale_RepID in the table-1
Can you please help with SQL Query?
My database is MS SQL SERVER
For MS SQL Server, please try:
UPDATE T
SET T.Products_Count=T.Products_Count+x.VSum
FROM Table1 T JOIN
(
SELECT DISTINCT
Sales_RepID,
SUM(Products_Count) OVER (PARTITION BY Sales_RepID) VSum
FROM
Table2
)x ON T.Sales_RepID=x.Sales_RepID
create table table1(sales_repId int,name varchar(10),product_count int);
create table table2(order_id int,sales_repId int,product_count int);
insert into table1 values(1,'ABC',2);
insert into table1 values(2,'XYZ',4);
insert into table1 values(3,'XXX',3);
insert into table2 values(1001,2,2);
insert into table2 values(1002,1,1);
insert into table2 values(1003,2,1);
insert into table2 values(1004,3,3);
insert into table2 values(1005,2,2);
select a.sales_repid,name,a.product_count+sum(b.product_count)
from table1 a
inner join table2 b
on a.sales_repid=b.sales_repid
group by a.sales_repid,name,a.product_count
order by a.sales_repid
UPDATE
update table1
set product_count = netProduct
from (
select a.sales_repid,name,a.product_count+sum(b.product_count) as netProduct
from table1 a
inner join table2 b
on a.sales_repid=b.sales_repid
group by a.sales_repid,name,a.product_count
) z
inner join table1 x
on z.sales_repid=x.sales_repid
TRY THIS
DECLARE #TABLE1 AS TABLE( Sales_RepID INT,Name VARCHAR(100), Products_Count int)
DECLARE #TABLE2 AS TABLE( Order_ID INT,Sales_RepID INT, Products_Count int)
INSERT INTO #TABLE1
VALUES(1,'ABC',2),(2,'XYZ',4),(3,'XXX',3)
INSERT INTO #TABLE2
VALUES(1001,2,2),(1002,1,1),(1003,2,1),(1004,3,3),(1005,2,2)
SELECT * FROM #TABLE1
SELECT * FROM #TABLE2
UPDATE T1
SET T1.Products_Count = T1.Products_count + total
FROM #TABLE1 T1
CROSS APPLY (
SELECT total= sum(Products_count)
FROM #Table2 T2
WHERE T1.Sales_RepID =t2.Sales_RepID ) Z
To output as a select:
select
t1.Sales_RepID,
t1.Name,
t1.Products_Count + sum(t2.Products_Count)
from table1 t1
left join table2 t2 on t2.Sales_RepID = t1.Sales_RepID
To update the total in table1, adding the total from table2:
update table1 set
Products_Count = Products_Count + (
select sum(Products_Count)
from table2
where Sales_RepID = table1.Sales_RepID)
These queries will work in all SQL dialects.
MS SQL Server has a special syntax for updating using a join, which will perform much better than the universal update syntax above:
update t1 set
t1.Products_Count = t1.Products_Count + t2.Products_Count
from table1 t1
join (select Sales_RepID, sum(Products_Count) Products_Count
from table2
group by Sales_RepID) t2
on t2.Sales_RepID = t1.Sales_RepID;
See a live demo of this update statement executing on SQLFiddle.
Note that this is an unusual query. Typically, such denormalized values are not cumulative: they are a determinable calculated value, which in this case wold be simply the sum, not the existing value plus the sum. Your design means that the query can only be executed once. After than you'll be repeatedly re-adding the total from table2.
Consider redesigning your tables to have the straight sum from table2 in table1, ie:
update t1 set
t1.Products_Count = t2.Products_Count
from table1 t1
join (select Sales_RepID, sum(Products_Count) Products_Count
from table2
group by Sales_RepID) t2
on t2.Sales_RepID = t1.Sales_RepID;

JOIN - Get one full table and the rest of another

Hi guys here is my Schema: http://sqlfiddle.com/#!4/82771
CREATE TABLE t1
(
Age INT,
Name VARCHAR(20)
);
CREATE TABLE t2
(
Age INT,
Name VARCHAR(20)
);
INSERT INTO t1(Age, Name) VALUES(31, NULL);
INSERT INTO t1(Age, Name) VALUES(32, NULL);
INSERT INTO t1(Age, Name) VALUES(33, NULL);
INSERT INTO t1(Age, Name) VALUES(34, NULL);
INSERT INTO t2(Age, Name) VALUES(31, 'Panos');
I need a Join query that will give me this Result:
Age Name
31 'Panos'
32 Null
33 Null
34 Null
I've tried LEFT JOIN and RIGHT JOIN on Age but I can't get what I need. It should be pretty simple but its just not coming to me...
maybe you have missed something when you are doing LEFT JOIN. Use also coalesce to return the first non-null value.
SELECT t1.Age, COALESCE(t2.name, t1.Name) Name
FROM t1
LEFT JOIN t2
ON t1.Age = t2.Age
SQLFiddle Demo
One way is to use union all and then check for non-existence in the second table:
select *
from t1
union all
select *
from t2
where Not exists (select 1 from t1 where t1.age = t2.age)

SQL Inner Join On Null Values

I have a Join
SELECT * FROM Y
INNER JOIN X ON ISNULL(X.QID, 0) = ISNULL(y.QID, 0)
Isnull in a Join like this makes it slow. It's like having a conditional Join.
Is there any work around to something like this?
I have a lot of records where QID is Null
Anyone have a work around that doesn't entail modifying the data
You have two options
INNER JOIN x
ON x.qid = y.qid OR (x.qid IS NULL AND y.qid IS NULL)
or easier
INNER JOIN x
ON x.qid IS NOT DISTINCT FROM y.qid
If you want null values to be included from Y.QID then Fastest way is
SELECT * FROM Y
LEFT JOIN X ON y.QID = X.QID
Note: this solution is applicable only if you need null values from Left table i.e. Y (in above case).
Otherwise
INNER JOIN x ON x.qid IS NOT DISTINCT FROM y.qid
is right way to do
This article has a good discussion on this issue. You can use
SELECT *
FROM Y
INNER JOIN X ON EXISTS(SELECT X.QID
INTERSECT
SELECT y.QID);
Are you committed to using the Inner join syntax?
If not you could use this alternative syntax:
SELECT *
FROM Y,X
WHERE (X.QID=Y.QID) or (X.QUID is null and Y.QUID is null)
I'm pretty sure that the join doesn't even do what you want. If there are 100 records in table a with a null qid and 100 records in table b with a null qid, then the join as written should make a cross join and give 10,000 results for those records. If you look at the following code and run the examples, I think that the last one is probably more the result set you intended:
create table #test1 (id int identity, qid int)
create table #test2 (id int identity, qid int)
Insert #test1 (qid)
select null
union all
select null
union all
select 1
union all
select 2
union all
select null
Insert #test2 (qid)
select null
union all
select null
union all
select 1
union all
select 3
union all
select null
select * from #test2 t2
join #test1 t1 on t2.qid = t1.qid
select * from #test2 t2
join #test1 t1 on isnull(t2.qid, 0) = isnull(t1.qid, 0)
select * from #test2 t2
join #test1 t1 on
t1.qid = t2.qid OR ( t1.qid IS NULL AND t2.qid IS NULL )
select t2.id, t2.qid, t1.id, t1.qid from #test2 t2
join #test1 t1 on t2.qid = t1.qid
union all
select null, null,id, qid from #test1 where qid is null
union all
select id, qid, null, null from #test2 where qid is null
Hey it is kind of late to answer that but I got the same question, what I realized is that you must have a record with the ID of 0 in you second table to make this :
SELECT * FROM Y
INNER JOIN X ON ISNULL(Y.QID, 0) = ISNULL(X.QID, 0)
to happen, it actually says if there is none, then use 0. BUT what if Y table does NOT have a record with the ID of 0?
So, I found this method, (and worked for my case):
SELECT
ISNULL(Y.QName, 'ThereIsNone') AS YTableQName
FROM
X
LEFT OUTER JOIN Y ON X.QID = Y.QID
A snapshot of my case
This way you DON'T need a record with 0 ID value in your second table (which is Y in this case and Customers in my case), OR any record at all
UPDATE:
You can also take a look at this post for better understanding.
Basically you want to join two tables together where their QID columns are both not null, correct? However, you aren't enforcing any other conditions, such as that the two QID values (which seems strange to me, but ok). Something as simple as the following (tested in MySQL) seems to do what you want:
SELECT * FROM `Y` INNER JOIN `X` ON (`Y`.`QID` IS NOT NULL AND `X`.`QID` IS NOT NULL);
This gives you every non-null row in Y joined to every non-null row in X.
Update: Rico says he also wants the rows with NULL values, why not just:
SELECT * FROM `Y` INNER JOIN `X`;
You could also use the coalesce function. I tested this in PostgreSQL, but it should also work for MySQL or MS SQL server.
INNER JOIN x ON coalesce(x.qid, -1) = coalesce(y.qid, -1)
This will replace NULL with -1 before evaluating it. Hence there must be no -1 in qid.