Display 0 when join is not successful - sql-server

I am using SQL Server to solve the following problem.
I have 3 tables T1, T2, T3
T1:
ID Name Country
----------------------
1 PR IN
2 AR US
T2:
ID AGE
------------
1 32
2 36
3 40
T3:
ID T1_ID T2_ID Amount
--------------------------------
1 1 1 100
2 1 2 300
Required output
T1.Name T2.Age T3.Amount
---------------------------------
PR 32 100
PR 36 200
PR 40 0
My query is :
select
T1.name, T2.Age, T3.amount
from
T3
join
T1 on T1.id = T3.T1_ID --fixed a typo here
right join
T2 on T2.id = T3.T2_ID
where
T1.id = 1
My current output is:
T1.Name T2.Age T3.Amount
--------------------------------
PR 32 100
PR 36 200
I would really appreciate any help on this

start the FROM statement on T2 and T1 because you want all records for T2 and T1 as a Cartesian product, limited by WHERE
instead of joining T3 in the FROM, using a subselect for T3 allows you to use ISNULL:
SELECT T1.NAME,
T2.age,
ISNULL((SELECT amount
FROM T3
WHERE T1.id = T3.T1_id
AND T2.id = T3.T2_id), 0) AS Amount
FROM T2 CROSS JOIN
T1
WHERE T1.id = 1

Related

SQL Server: Cross-apply - record 0 for NULL results

T1 is a table of company and their (multiple users), T2 is table of registered users. I counted, for each company in T1, how many of their users are in T2 but need c3 to appear in the result table with #regUser == 0:
T1:
company user
c1 u1
c1 u2
c2 u2
c2 u3
c3 u4
c3 u1
T2:
user
u2
u3
So the resultant table should look like:
company #regUser
c1 1
c2 2
c3 0
With the following code I'm only getting the results for non-null companies:
select t1s.company, count(1)
from (select * from t1) t1s
cross apply (select *
from t2 t2s
where t2s.reguser = t1s.[user]) t12s
group by t1s.company
Thanks
just use left join
select t1.company,count(t2.user)
from t1 left join t2 on t1.user=t2.user
group by t1.company
the subquery is not necessary according to your requirement
but if you want to use apply then you need like below query
select t1s.company, count(t12s.Users)
from (select * from t1) t1s
outer apply (select Users
from t2 t2s
where t2s.Users = t1s.[Users]) t12s
group by t1s.company
output
company #regUser
c1 1
c2 2
c3 0
demolink
You can use a LEFT JOIN to get all the information of the left table with matching information from right table. By using a GROUP BY you can group the rows by company and get the COUNT of registered users for each company:
SELECT t1.company, COUNT(t2.[user]) AS regUser
FROM t1 LEFT JOIN t2 ON t1.[user] = t2.[user]
GROUP BY t1.company
ORDER BY t1.company ASC
You can also use the CROSS APPLY to solve this:
SELECT t1.company, SUM(CASE WHEN t1.[user] = t2.[user] THEN 1 ELSE 0 END) AS regUser
FROM t1 CROSS APPLY t2
GROUP BY t1.company
ORDER BY t1.company ASC
demo on dbfiddle.uk
All you need is a left join :
select company,count(t2.[user])
from t1 left outer join t2 on t1.[user]=t2.[user]
group by company
The question's query is overcomplicated. For example, from (select * from t1) t1s is equivalent to from t1 as t1s.
Just a LEFT JOIN with SUM()
CREATE TABLE T1(
Company VARCHAR(20),
Users VARCHAR(20)
);
CREATE TABLE T2(
Users VARCHAR(20)
);
INSERT INTO T1 VALUES
('c1', 'u1'),
('c1', 'u2'),
('c2', 'u2'),
('c2', 'u3'),
('c3', 'u4'),
('c3', 'u1');
INSERT INTO T2 VALUES
('u2'),
('u3');
SELECT T1.Company,
SUM(CASE WHEN T2.Users IS NULL THEN 0 ELSE 1 END) Cnt
FROM T1 LEFT JOIN T2
ON T1.Users = T2.Users
GROUP BY T1.Company;
Returns:
+---------+-----+
| Company | Cnt |
+---------+-----+
| c1 | 1 |
| c2 | 2 |
| c3 | 0 |
+---------+-----+
Live Demo

SQL Server query about joining 2 table with union

I have two tables T1 and T2, both of them contain a column ID and value.
I need to join T1 and T2 into T3 by means of ID.
T3 should contain columns ID, T1Value, and T2Value.
The main requirement is, ID of T1 and T2 is possible not mapped
T1:
ID VALUE
-----------
1 hi
2 hello
T2:
ID VALUE
----------
2 kitty
3 dog
Then, T3 should be
ID T1VALUE T2VALUE
----------------------
1 hi
2 hello kitty
3 dog
Is it possible to achieve this without using pivot table, or temp table (ideally should be a single executable query)?
Thanks.
You can use FULL OUTER JOIN
SELECT ID = COALESCE(T1.ID, T2.ID),
T1VALUE = T1.VALUE,
T2VALUE = T2.VALUE
FROM T1
FULL OUTER JOIN T2
ON T1.ID = T2.ID
There are lots of example on FULL OUTER JOIN . just search for it
Another way is to use UNION ALL
SELECT T1.ID, T1VALUE = T1.VALUE, T2VALUE = NULL
FROM T1
UNION ALL
SELECT T2.ID, T1VALUE = NULL, T2VALUE = T2.VALUE
FROM T2

Join three tables in SQL Server 2008

I have three tables.
A
ID NAME
--- ----
1 abc
2 asd
3 qwe
B
ID INCOME
--- ------
1 2
2 3
1 4
C
NAME TOTAL
---- ----
abc 8
asd 20
I want to join this three tables with a SQL query to produce an output like
ID INCOME TOTAL
---------------
1 6 8
2 3 20
Could anyone help me?
You could try this:
select
t1.id, sum(t2.income) income, sum(t3.total) total
from
table1 t1
join
table2 t2 on t1.id = t2.id
join
table3 t3 on t3.name = t1.name
group by
t1.id
order by
t1.id

Using Joins to get all data from left table

I have two tables as shown below.
Id Name Id Status
-------- -------------------
1 A 1 Approved
2 B 6 Approved
3 C 4 Pending
4 D 1 Approved
5 E 1 Pending
6 F 3 Pending
5 Rejected
Now this is how I want the output to be:
Id Name Status
-------------------
1 A Pending
2 B
3 C Pending
4 D Pending
5 E
6 F
I have tried using left join but I am getting multiple rows.
select t1.ID,Name,Status from t1 left join t2 on t1.id=t2.id
and if I add where Status=pending i am getting only ids 1 and 3.
Here are the queries i tried:
select distinct t1.id,name,status from t1 left join t2 on t1.id=t2.id (this gives me duplicate records i.e id 1 is occurs twice with approved and pending)
and also
select distinct t1.id,name,status from t1 left join t2 on t1.id=t2.id where t2.status='pending' (gives me only 1,3 and 4)
Could any one help me,
Thanks in advance.
To include all rows from T1 and only those from T2 with status = 'pending' move the condition into the ON clause SQL Fiddle
SELECT t1.ID,
Name,
Status
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
AND t2.status = 'pending'
To only return one row per id in the event of dupes you could do (Fiddle)
WITH CTE AS
(
SELECT DISTINCT id, Status
FROM T2
WHERE Status = 'Approved'
)
SELECT t1.ID,
Name,
Status
FROM t1
LEFT JOIN CTE
ON t1.id = CTE.id

Case function in MS SQL

I have a table of format
id name flag
----------------
11 Jack 1
11 Jill 2
23 Joe 1
23 John 2
23 Sam 1
46 White 2
46 Dan 2
57 Dave 1
I am trying to return the table of format (based on the flag for particular id) like
id name_1 name_2
------------------
11 Jack Jill
23 Joe John
23 Sam John
46 NULL White
46 NULL Dan
57 Dave NULL
I tried this query but it does not give the expected result.
select id,
case flag when 1 then name end as name_1,
case flag when 2 then name end as name_2
from temp;
You want a join, not a select case. Something like this, assuming null is possible in either column:
SELECT a.id, a.name fname, b.name lname from
(SELECT id, name FROM temp WHERE flag = 1) a
full outer join
(SELECT id, name FROM temp WHERE flag = 2) b on a.id = b.id
Not sure what you expect in this case though:
46 NULL White
46 NULL Dan
I don't think you're going to be able to use case for this. This should do the trick, however:
select t1.id, t1.name as name_1, t2.name as name_2
from temp t1
inner join temp t2 on t1.id = t2.id and t1.flag = 1 and t2.flag = 2
I'm not sure you can get your partial result from the same query, so you could always do a union to find these...
select t1.id, t1.name as name_1, t2.name as name_2
from temp t1
inner join temp t2 on t1.id = t2.id and t1.flag = 1 and t2.flag = 2
union
select t1.id, t1.name as name_1, t2.name as name_2
from temp t1
left join temp t2 on t1.id = t2.id and t1.flag = 1 and t2.flag = 2
where t2.id is null
union
select t2.id, t1.name as name_1, t2.name as name_2
from temp t2
left join temp t1 on t1.id = t2.id and t1.flag = 1 and t2.flag = 2
where t1.id is null
This will get totally screwed up if there are 3 rows with the same ID :)

Resources