Counting from 2 tables - sql-server

I have 2 tables.
A
Id Name
1 ab
2 cd
3 eg
4 fg
B
FkID
1
2
2
1
1
2
4
Since 3 is not there in B in the FKID column. I need to find the count in table A which has value in table B which have a value in FKID also.
So th total count should be 3. In my query, I am getting 7 after the left join.

You don't need a join, you can do it with EXISTS:
select count(*) from a
where exists (
select 1 from b
where b.fkid = a.id
)
I believe EXISTS is more efficient than a join, but if you need a join then it has to be an INNER JOIN like this:
select count(distinct a.id)
from a inner join b
on b.fkid = a.id

Using COUNT(DISTINCT B.FkId) the result can be achiveable. The COUNT is not considering the NULL values, so the following query will work.
SELECT COUNT(DISTINCT B.FkId) AS Occurence
FROM TableA A
LEFT JOIN TableB B ON B.FkId = A.Id;
or it can be achiveable with INNER JOIN too
SELECT COUNT(DISTINCT B.FkId) AS Occurence
FROM TableA A
INNER JOIN TableB B ON B.FkId = A.Id;
Demo with sample data:
DECLARE #TableA TABLE (Id INT, [Name] VARCHAR (2));
INSERT INTO #TableA (Id, [Name]) VALUES
(1, 'ab'),
(2, 'cd'),
(3, 'eg'),
(4, 'fg');
DECLARE #TableB TABLE (FkId INT);
INSERT INTO #TableB (FkId) VALUES
(1),
(2),
(2),
(1),
(1),
(2),
(4);
SELECT COUNT(DISTINCT B.FkId) AS Occurence
FROM #TableA A
LEFT JOIN #TableB B ON B.FkId = A.Id

Related

How to select from table one with all records from table 2

I am trying to display all records that table 1 contains, each record with all the records from table 2 :
Table 1
company adress
------------------
A AdressX
B AdressY
C AdressZ
Table 2
Product Price
----------------
P1 50
P2 60
Result :
company Product
----------------
A P1
A P2
B P1
B P2
C P1
C P2
That would be a cross join.
SELECT t1.company,
t2.product
FROM [table 1] t1
CROSS JOIN [table 2] t2
ORDER BY t1.company,
t2.product;
Using CROSS APPLY this exected output is possible:
SELECT T1.company, T2.Product
FROM Table1 T1
CROSS APPLY Table2 T2
ORDER BY T1.company, T2.Product
Demo on db<>fiddle
Demo with sample data:
DECLARE #Table1 TABLE (company VARCHAR (1), adress VARCHAR (10));
INSERT INTO #Table1 (company, adress) VALUES
('A', 'AdressX'),
('B', 'AdressY'),
('C', 'AdressZ');
DECLARE #Table2 TABLE (Product VARCHAR (2), Price INT);
INSERT INTO #Table2 (Product, Price) VALUES
('P1', 50),
('P2', 60);
SELECT T1.company, T2.Product
FROM #Table1 T1
CROSS APPLY #Table2 T2
ORDER BY T1.company, T2.Product
Output:
company Product
---------------
A P1
A P2
B P1
B P2
C P1
C P2
The following query will select all data from both tables (not linked or related).
SELECT *
FROM TABLE 1
OUTER APPLY
(
SELECT *
FROM Table 2
) AS Table 2
If there is a foreign key, you can use a LEFT JOIN (SELECT)

Query in SQL Server to combine tables

I need a query in SQL Server to combine tables like these:
TBL1
ID TITLE1
-----------
1 t1
2 t2
3 t3
TBL2
ID TITLE2
------------
100 c1
200 c2
Now I need tbl3 as a result:
TBL3
col1 col2
-----------
t1 c1
t1 c2
t2 c1
t2 c2
t3 c1
t3 c2
How can I get tbl3 without any key between these 2 tables?
You are looking for a cross join:
SELECT
t1.TITLE1 AS col1,
t2.TITLE2 AS col2
FROM TBL1 t1
CROSS JOIN TBL2 t2
ORDER BY
t1.TITLE1,
t2.TITLE2;
Demo
You can try this
CREATE TABLE #Table1
([ID] int, [TITLE1] varchar(2))
INSERT INTO #Table1
VALUES
(1, 't1'),
(2, 't2'),
(3, 't3')
CREATE TABLE #Table2
([ID] int, [TITLE2] varchar(2))
INSERT INTO #Table2
VALUES
(100, 'c1'),
(200, 'c2')
SELECT Title1 as col1, Title2 as col2
FROM #Table1
CROSS JOIN #Table2 order by Title1
DROP TABLE #Table1
DROP TABLE #Table2
Here is the output shown below.
col1 col2
t1 c1
t1 c2
t2 c2
t2 c1
t3 c1
t3 c2
CROSS JOIN will work for your case.
That is result-set contains the number of rows in the first table, multiplied by the number of rows in second table when there is no WHERE clause.
/**********************************/
SELECT
a.TITLE1 AS col1,
b.TITLE2 AS col2
FROM
TBL1 a
CROSS JOIN
TBL2 b
/**********************************/

How to join two Tables which have no unique ID

I am trying to Left join Table 1 to table 2
Table1 Table2
ID Data ID Data2
1 r 1 q
2 t 1 a
3 z 2 x
1 u 3 c
After i have left joined this two Tables i would like get something like this
Table1+2
ID Data Data2
1 r a
2 t x
3 z c
1 u q
and NOT
Table1+2
ID Data Data2
1 r q
2 t x
3 z c
1 u q
and my question is: is there any possibility to tell table 2 that if u have used something for table 1, dont use it and give me next value. do i have to make it im T-SQL or to and new column where i can list if this id exists then write 2 if not 1(Number data). How can i solve this problem?
Ty u in advance.
Since there's no uniqueness in the ID on both tables, lets add some uniqueness to it.
So it can be used to join on.
The window function ROW_NUMBER can be used for that.
An example solution that gives the expected result:
DECLARE #TestTable1 TABLE (ID INT, Data VARCHAR(1));
DECLARE #TestTable2 TABLE (ID INT, Data VARCHAR(1));
INSERT INTO #TestTable1 VALUES (1,'r'),(2,'t'),(3,'z'),(1,'u');
INSERT INTO #TestTable2 VALUES (1,'q'),(1,'a'),(2,'x'),(3,'c');
select
t1.ID, t1.Data,
t2.Data as Data2
from (
select ID, Data,
row_number() over (partition by ID order by Data) as rn
from #TestTable1
) t1
left join (
select ID, Data,
row_number() over (partition by ID order by Data) as rn
from #TestTable2
) t2 on t1.ID = t2.ID and t1.rn = t2.rn;
Note: Because of the LEFT JOIN, this does assume the amount of same ID's in table2 are equal or lower can those on table1. But you can change that to a FULL JOIN if that's not the case.
Returns :
ID Data Data2
1 r a
1 u q
2 t x
3 z c
To get the other result could have been achieved in different ways.
This is actually a more common situation.
Where one wants all from Table 1, but only get one value from Table 2 for each record of Table 1.
1) A top 1 with ties in combination with a order by rownumber()
select top 1 with ties
t1.ID, t1.Data,
t2.Data as Data2
from #TestTable1 t1
left join #TestTable2 t2 on t1.ID = t2.ID
order by row_number() over (partition by t1.ID, t1.Data order by t2.Data desc);
The top 1 with ties will only show those where the row_number() = 1
2) Using the row_number in a subquery:
select ID, Data, Data2
from (
select
t1.ID, t1.Data,
t2.Data as Data2,
row_number() over (partition by t1.ID, t1.Data order by t2.Data desc) as rn
from #TestTable1 t1
left join #TestTable2 t2 on t1.ID = t2.ID
) q
where rn = 1;
3) just a simple group by and a max :
select t1.ID, t1.Data, max(t2.Data) as Data2
from #TestTable1 t1
left join #TestTable2 t2 on t1.ID = t2.ID
group by t1.ID, t1.Data
order by 1,2;
All 3 give the same result:
ID Data Data2
1 r q
1 u q
2 t x
3 z c
Use ROW_NUMBER
DECLARE #Table1 TABLE (ID INT, DATA VARCHAR(10))
DECLARE #Table2 TABLE (ID INT, DATA VARCHAR(10))
INSERT INTO #Table1
VALUES
(1, 'r'),
(2, 't'),
(3, 'z'),
(1, 'u')
INSERT INTO #Table2
VALUES
(1, 'q'),
(1, 'a'),
(2, 'x'),
(3, 'c')
SELECT
A.*,
B.DATA
FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY(SELECT NULL)) RowId FROM #Table1) A INNER JOIN
(SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY(SELECT NULL)) RowId FROM #Table2) B ON A.ID = B.ID AND
A.RowId = B.RowId

Select record from table1 where value from table2

I have 2 tables here:
table1
id name idfrom idto
1 test 2 3
2 test3 1 9
table2
id branch status
2 a from
1 b from
9 c to
3 d to
How do I select branch from table2 and table1 based on status in table2?
I want the result to look like this:
id name branchfrom branchto
1 test a d
2 test3 b c
I answer it doesn't mean I like it.
SELECT id, name, bfrom.branch branchfrom, bto.branch branchto
FROM table1 t1
INNER JOIN (SELECT id, branch
FROM table2
WHERE status = 'from') bfrom
ON t1.idfrom = bfrom.id
INNER JOIN (SELECT id, branch
FROM table2
WHERE status = 'to') bto
ON t1.idto = bto.id;
I use INNER JOIN as sample only. You must adjust with your requirement (which you didn't clearly specify).
Something like the following should do (assuming you're wanting to join on id in both tables):
select t1.id, t1.name, f.branch as branchfrom, t.branch as branchto
from table1 as t1
join table2 as f
on f.id = t1.id
and f.status = 'from'
join table2 as t
on t.id = t1.id
and t.status = 'to'
This should work for you:
select t1.id, t1.name, f.branch as branchfrom, f1.branch as branchto
from table1 as t1
join table2 as f
on t1.idfrom = f.id
join table2 as f1
on t1.idto = f1.id
Please see here for demo: SQL Fiddle Demo
I don't know if this is better or worse than what the other two people have suggested but
select
t1.name,
(select
t2.branch
from
table2 t2
where
t1.idfrom = t2.id
) as branchfrom,
(select
t2.branch
from
table2 t2
where
t1.idto = t2.id
) as branchto
from
table1 t1
Here is a fiddle
Use this Code:
CREATE TABLE #table1 (
id int,
name varchar(10),
idfrom int,
idto int
)
CREATE TABLE #table2 (
id int,
branch char,
statuss varchar(10)
)
INSERT INTO #table1
VALUES (1, 'test', 2, 3)
INSERT INTO #table1
VALUES (2, 'test3', 1, 9)
INSERT INTO #table2
VALUES (2, 'a', 'From')
INSERT INTO #table2
VALUES (1, 'b', 'From')
INSERT INTO #table2
VALUES (9, 'c', 'to')
INSERT INTO #table2
VALUES (3, 'd', 'to')
SELECT
a.id,
a.name,
(SELECT
b.branch
FROM #table2 b
WHERE a.idfrom = b.id
AND b.statuss = 'FROM')
AS BranchFrom,
(SELECT
b.branch
FROM #table2 b
WHERE a.idto = b.id
AND b.statuss = 'to')
AS BranchTo
FROM #table1 a

Inner join then full join among the matched records

I have two tables:
declare #Table1 as table (id int, value CHAR(1))
declare #Table2 as table (id int, value CHAR(1))
INSERT #Table1
VALUES (1, 'A'),
(1, 'B'),
(3, 'A')
INSERT #Table2
VALUES(1, 'A'),
(1, 'C'),
(2, 'A')
I want to join these two tables so that at the end I should be able to produce this result:
id value id value
1 A 1 A
1 B NULL NULL
NULL NULL 1 C
I'm sorry for inadequate explanation (I mean no explanation at all). What I am trying to do here is (something like) to make inner join for the id columns (I mean take the records which are common on both sets over the "id" column) then look at the value columns and compare them inside the boundaries of this common set.
I hope I could describe what I was trying to do.
Hope this will work
SELECT distinct t1_id as id, t1_value as value , t2_id as id , t2_value as value
FROM (SELECT t1.id as t1_id, t1.value as t1_value from #Table1 t1 INNER JOIN #Table2 t2 on t1.id = t2.id) as A
FULL OUTER JOIN
(SELECT t2.id as t2_id, t2.value as t2_value from #Table1 t1 INNER JOIN #Table2 t2 on t1.id = t2.id) as B
on A.t1_value = B.t2_value
ORDER BY t1_id desc
Basically, What I am doing is outer joining the inner set (which is inner join on id column) on value column of inner set.
What do I win?
SELECT c.id,c.value,d.id,d.value
FROM
#Table1 c
full join
#Table2 d
on c.id = d.id and c.value = d.value
WHERE exists
(
SELECT a.id
FROM
#Table1 a
INNER JOIN
#Table2 b
ON a.id = b.id and a.id = c.id or d.id = a.id
)
You can do this with a full outer join and by pre-filtering the tables:
select a.id as a_id, a.value as a_value,
b.id as b_id, b.value as b_value
from (select *
from tablea a
where a.id = 1
) a full outer join
(select *
from tableb b
where b.id = 1
) b
on a.id = b.id and a.value = b.value;

Resources