Select query to get counts - sql-server

I have 2 tables that I want to query against. If a record exists in both tables then count record and assign to Both, if record exist in Table 1 (T1 Only), then count it and assign to T1 Only, if record exists in Table 2 (T2 Only), then count it and assign to T2 Only column. Have the result set come out as follows.
Both T1 Only T2 Only
2000 3000 4000

Use a FULL JOIN. It will return all records from both tables in the query. See example below for your desired result.
CREATE TABLE #Table1 (Id INT);
CREATE TABLE #Table2 (Id INT);
INSERT INTO #Table1 VALUES (1), (2), (3), (4), (5), (6);
INSERT INTO #Table2 VALUES (3), (4), (5), (6), (7);
SELECT
SUM(CASE WHEN T1.Id IS NOT NULL AND T2.Id IS NOT NULL THEN 1 ELSE 0 END) AS Both
, SUM(CASE WHEN T1.Id IS NOT NULL AND T2.Id IS NULL THEN 1 ELSE 0 END) AS T1Only
, SUM(CASE WHEN T1.Id IS NULL AND T2.Id IS NOT NULL THEN 1 ELSE 0 END) AS T2Only
FROM #Table1 AS T1 FULL JOIN #Table2 AS T2 ON T2.Id = T1.Id;

Related

Joining tables without a common column in sql server

TABLE1
ID
----
1
2
3
4
5
TABLE2
Name
----
Z
Y
X
W
V
Expected Output:
ID Name
-------------------------
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
NULL Z
NULL Y
NULL X
NULL W
NULL V
I need a solution for the above scenario by using JOINS in SQL Server.
Using FULL OUTER JOIN, you can get the expected result.
Since there are no common fields, no records from Table1 should match with Table2 and vice versa. So perhaps ON 0 = 1 as the join condition also will work as expected. Thanks Bart Hofland
So the query below also will work:
SELECT T1.Id, T2.[Name]
FROM Table1 T1
FULL OUTER JOIN Table2 T2 ON 0 = 1;
or
SELECT T1.Id, T2.[Name]
FROM Table1 T1
FULL OUTER JOIN Table2 T2 ON T2.[Name] = CAST(T1.Id AS VARCHAR(2));
Demo with the sample data:
DECLARE #Table1 TABLE (Id INT);
INSERT INTO #Table1 (Id) VALUES
(1),
(2),
(3),
(4),
(5);
DECLARE #Table2 TABLE ([Name] VARCHAR(1));
INSERT INTO #Table2 ([Name]) VALUES
('Z'),
('Y'),
('X'),
('W'),
('V');
SELECT T1.Id, T2.[Name]
FROM #Table1 T1
FULL OUTER JOIN #Table2 T2 ON 0 = 1;
Output:
Id Name
-----------------
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
NULL Z
NULL Y
NULL X
NULL W
NULL V
I don't understand why you'd want this, but to get your expected results you could do this. This is not a join, though.
SELECT ID, NULL as NAME from Table1
UNION ALL
SELECT NULL, NAME from Table2
Edited to add
Since the question specifically requests a solution with a join, Arulkumar's answer of FULL OUTER JOIN is a better fit, and you don't have to worry about what the column data types are.

Counting from 2 tables

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

Why does UNION returns only one null?

I understand null represents missing/unknown value, so a null is not equal to another null because two unknown things cannot be compared. For example
if null = null
select 'nulls are equal'
else
select 'nulls are not equal'
results in 'nulls are not equal' I used an = instead of is null or is not null here to emphasize the fact that two nulls cannot be compared.
Coming to UNION, UNION is supposed to eliminate duplicate values. I was expecting the below code to return two rows each with null since two null values are not equal, but I get only one null in the result set.
(select null as Col1)
union
(select null as Col1)
Why does SQL's interpretation of 'null as an unknown value' change in above two statements?
NULL is not comparable, but SQL generally does have the concept of "IS DISTINCT FROM"
SQL Server has a Connect item for it
1 IS DISTINCT FROM NULL = true
1 = null is false
For completeness, NULL IS DISTINCT FROM NULL = false
I would guess that DISTINCT and UNION use IS DISTINCT FROM (as Pரதீப் mentioned above)
Now, SQL Server does have IS DISTINCT FROM in INTERSECT and EXCEPT
DECLARE #t1 TABLE (t1col INT);
INSERT #t1 VALUES (1), (NULL), (2), (3), (3), (5), (5);
DECLARE #t2 TABLE (t2col INT);
INSERT #t2 VALUES (1), (NULL), (3), (4);
SELECT DISTINCT 't1 EXISTS t2', *
FROM #t1 t1 WHERE EXISTS (SELECT * FROM #t2 t2 WHERE t1.t1col = t2.t2col);
t1 EXISTS t2 1
t1 EXISTS t2 3
t1 EXISTS t2 3
SELECT DISTINCT 't1 INTERSECT t2', *
FROM #t1 INTERSECT SELECT 't1 INTERSECT t2', * FROM #t2;
t1 INTERSECT t2 NULL
t1 INTERSECT t2 1
t1 INTERSECT t2 3
INTERSECT and EXCEPT also remove duplicates because they do a semi-join
EXISTS is an anti-join BTW
For completeness
SELECT 't1 EXISTS t2', *
FROM #t1 t1 WHERE NOT EXISTS (SELECT * FROM #t2 t2 WHERE t1.t1col = t2.t2col);
t1 EXISTS t2 NULL
t1 EXISTS t2 2
t1 EXISTS t2 5
t1 EXISTS t2 5
SELECT 't1 EXCEPT t2', *
FROM #t1 EXCEPT SELECT 't1 EXCEPT t2', * FROM #t2;
t1 EXCEPT t2 2
t1 EXCEPT t2 5
Example taken from my answer Why does EXCEPT exist in T-SQL? with added NULLs
UNION is basically SELECT DISTINCT, so it would be eliminating duplicate NULL values, but it's not the same as Equal operation.
Using UNION ALL would give you all records including duplicating NULLs.
As for the first part of you question. NULL really equals NULL, but not with "=". This would give you result you expect:
if null IS null
select 'nulls are equal'
else
select 'nulls are not equal'
This is also helpful when dealing with nulls.
Try UNION ALL to retain everything in both sets without removing duplicates.

Set field to random value from another table

update table1
set firstname = (select top 1 firstname from table2 order by NEWID())
This just sets table1.firstname to the same value for all records. I know it's possible to do this, but everything I've seen online expects the same row count in both tables (or at least a greater amount in table1). I have 200,000 records in table1, I have 200 in table2. How can I set table1.firstname to a random value from table2.firstname when the row counts are off?
DECLARE #t1 TABLE (a INT)
DECLARE #t2 TABLE (b INT, c INT)
INSERT INTO #t1(a)
VALUES (0), (1), (2), (3), (4), (5)
INSERT INTO #t2(b)
VALUES (0), (1), (2)
UPDATE t2
SET c = t1.a
FROM #t2 t2
CROSS APPLY (
SELECT TOP(1) t1.a
FROM #t1 t1
WHERE t2.b IS NOT NULL -- any calculations for t2 columns
ORDER BY NEWID()
) t1
SELECT * FROM #t2
Output -
b c
----------- -----------
0 5
1 1
2 0

Case-when w.r.to Count in sql server

I am getting error in the below sql query.
if count is >1 i need to execute when statement, if not else statement.
SELECT CASE
WHEN (COUNT(VALUE) FROM TABLE1 WHERE ID=111)>1 )
THEN
SELECT VALUE FROM TABLE2 WHERE ID=111
ELSE
SELECT 2
Please help
Try this:
if (select count(*) from table1 where id = 111 group by id) > 1
select value from table2 where id = 111
else
select 2
Demo
The same thing, written using case when...
select
case
when (select count(*) from table1 where id = 111 group by id) > 1 then value
else 2
end
from table2
where id = 111
Try this sample code
DECLARE #Table1 TABLE
(
id INT,
value INT
)
INSERT #Table1
VALUES(1,
10)
INSERT #Table1
VALUES(2,
20)
DECLARE #TABLE2 TABLE
(
id INT,
c2 INT
)
INSERT #TABLE2
VALUES(1,
11 )
INSERT #TABLE2
VALUES(2,
22 )
SELECT CASE
WHEN (SELECT count(value)
FROM #Table1) > 0 THEN (SELECT T2.c2
FROM #TABLE2 T2
WHERE T1.id = T2.id)
ELSE (SELECT T2.id
FROM #TABLE2 T2
WHERE T1.id = T2.id)
END
FROM #Table1 t1
IF EXISTS(SELECT TOP 1 1 FROM TABLE1 WHERE ID='111' HAVING COUNT(VALUE)>1)
BEGIN
SELECT VALUE FROM TABLE2 WHERE ID=111
END
ELSE
BEGIN
SELECT 2
END

Resources