Join between Parent and Child table - sql

I've 2 tables: Parent and Child with following data
Now when I execute the following queries:
delete from Parent where Id in(2,3,4)
delete from Child
The only record is left Parent table
Now when I execute the following query I don't get any records
select p.Id AS [ParentId],p.Name AS [ParentName], c.Id, c.Name from Parent p
Left join Child c on p.Id = c.ParentId
where p.IsActive = 1 and c.IsActive = 1
And when I remove and c.IsActive = 1 from above query I get the record in Package table, but I want to apply both the active checks. How to achieve this?

Your where clause turns your left join into an inner join. Use
select p.Id AS [ParentId],p.Name AS [ParentName], c.Id, c.Name
from Parent p
Left join Child c on p.Id = c.ParentId
and c.IsActive = 1
where p.IsActive = 1
All filters of the left joined table need to be in the on clause.

Another solution is to treat both cases in the where clause condition (both when c.IsActive is null - missing row in child table - or is 1)
where p.IsActive = 1 and COALESCE(c.IsActive, 1) = 1

Related

SQL where clause in nested query with column that doesnt exist in nested query

I wrote the following query and it works:
select * from processed p
inner join data d on d.dataId = p.dataid
where assetid in (select a.assetid from dbo.file f
inner join asset a on a.assetName = f.fileNumber
inner join configMapping c on c.assetId = a.assetid
WHERE p.id in (2,11) and rawConfig = 1)
However, I realised this shouldn't work. The query should be written as:
select * from processed p
inner join data d on d.dataId = p.dataid
where assetid in (select a.assetid from dbo.file f
inner join asset a on a.assetName = f.fileNumber
inner join configMapping c on c.assetId = a.assetid
WHERE rawConfig = 1)
and p.id in (2,11)
The nested query is only looking for assetid's. Furthermore, running the nested query on its own wouldn't work because id isn't in those three tables:
select a.assetid from dbo.file f
inner join asset a on a.assetName = f.fileNumber
inner join configMapping c on c.assetId = a.assetid
WHERE p.id in (2,11) and rawConfig = 1
Msg 207, Level 16, State 1, Line 44
Invalid column name 'id'.
Apologies for not having testable data to provide, but essentially the question is how does the first query's nested query use a where on a column from its parent query. Logically I would think the nested query would fail and thus the whole query should fail.
I'm using the newest version of SSMS
You have to add condition in the select using case I have shifted the ContractDate but if it doesn't work then you have to shift other conditions too
Select
SUM(case when c.ContractDate >= #ContractDate then c.Price else 0 end) As 'TotalPrice',
SUM(case when c.ContractDate >= #ContractDate then 1 else 0 end) As 'ContractCount'
from Rsv_Contract as c
where c.RegisterUsersId = #RegisterUsersId
and c.contractstate in (1,2)
and c.ContractNumber!='0000000'
and c.ContractNumber!='-1'
Group by CAST(c.ContractDate AS DATE)
You can use EXISTS clause of sql.
select *
from processed p
join data d
on d.dataid = p.dataid
where p.id in (2, 11)
and exists (select 1
from dbo.file f
join asset a
on a.assetname = f.filenumber
join configmapping c
on c.assetid = a.assetid
where a.assetid = p.asset_id
and rawconfig = 1)
Sorry guys, my bad not mentioning the code beforehand.
Hope this will solve your problem.
I found the answer here:
https://learn.microsoft.com/en-us/sql/relational-databases/performance/subqueries?view=sql-server-2017
Important
If a column is referenced in a subquery that does not exist in the table referenced by the subquery's FROM clause, but exists in a table referenced by the outer query's FROM clause, the query executes without error. SQL Server implicitly qualifies the column in the subquery with the table name in the outer query.
It will effectively refactor the query into a series of joins before executing.

Select an ID where there is only one row and that row is a specific value

I have this query. There's a lot of joins because I am checking if an ID is linked to any of those tables.
Currently, this query shows me any ID's that are not linked to any of those tables. I would like to add to it so that it also shows any IDs that are linked to the d table, but only if there is only 1 row in the D table and the type in the D field is 'member'.
SELECT
c.ID,
c.location,
c.pb,
c.name,
c.surname
FROM c
LEFT JOIN l on c.rowno = l.rowno
LEFT JOIN d on c.rowno = d.rowno
LEFT JOIN t on c.rowno = t.rowno
LEFT JOIN cj ON (c.rowno = cj.rowno OR c.rowno = cj.rowno2)
LEFT JOIN dj ON c.rowno = d.rowno
LEFT JOIN lg ON c.rowno = lg.rowno
LEFT JOIN tj ON c.rowno = tj.rowno
WHERE
c.status != 'closed'
AND l.rowno IS NULL
AND d.rowno IS NULL
AND t.rowno IS NULL
AND cj.rowno IS NULL
AND dj.rowno IS NULL
AND lg.rowno IS NULL
AND tj.rowno IS NULL
My first thought is to just add
WHERE D.type = 'member'
But that gives me all IDs that have a row with D.type = member (they could have 10 rows with all different types, but as long as 1 of those has type = member it shows up). I want to see ID's that ONLY have d.type = member
I'm sorry if I'm wording this badly, I'm having trouble getting this straight in my head. Any help is appreciated!
I would use exists for all conditions except the one on the D table:
SELECT c.*
FROM c JOIN
(SELECT d.rownum, COUNT(*) as cnt,
SUM(CASE WHEN d.type = 'Member' THEN 1 ELSE 0 END) as num_members
FROM t
GROUP BY d.rownum
) d
ON c.rownum = d.rownum
WHERE c.status <> 'closed' AND
NOT EXISTS (SELECT 1 FROM t WHERE c.rowno = t.rowno) AND
NOT EXISTS (SELECT 1 FROM l WHERE c.rowno = l.rowno) AND
. . .
I find NOT EXISTS is easier to follow logically. I don't think there is a big performance difference between the two methods in SQL Server.

Dynamically decide join table based on column value

I want to dynamically inner join tables, here is my SQL query
Update temp
Set temp.Order_Id = parent.ID
from #TempTransactions AS temp
Inner Join (case when temp.OrderType = 1 then preorders else orders end) AS parent
ON parent.Cloud_Id = temp.Order_Id
Is it possible I can decide in above way or any other alternative?
If yes, how?
Two Left joins would do.
Update temp Set temp.Order_Id = COALESCE(p.ID, o.ID)
from #TempTransactions AS temp
LEFT Join preorders p ON p.Cloud_Id = temp.Order_Id AND temp.OrderType=1
LEFT JOIN orders o ON o.Cloud_Id = temp.Order_Id AND (temp.OrderType <> 1 OR temp.OrderType IS NULL)
WHERE COALESCE(p.ID, o.ID) IS NOT NULL

WebSQL selecting child + parent

I'm trying to export a list of categories with it's childs.
the designer of the DB made it so that a parent category can have the same ID of a child
so the query should return a list of:
Parent items
Child items with the parent name
I'm trying to do this in 1 Query, So I did the following:
SELECT DISTINCT c.*, pc.name as parentName
FROM Category as c
INNER JOIN Category as pc on c.parent_id = pc.id
WHERE c.building_id = 1
AND (
c.parent_id = -1
OR (
c.usingtemplate = 'true'
AND
pc.parent_id = -1
)
);
but the parents aren't in the list
I have a sql fiddle here: http://sqlfiddle.com/#!7/75dd9/83
Doing a LEFT JOIN did the trick
SELECT DISTINCT c.*, pc.name as parentName
FROM Category as c
LEFT JOIN Category as pc on c.parent_id = pc.id
WHERE c.building_id = 1
AND (
c.parent_id = -1
OR (
c.usingtemplate = 'true'
AND
pc.parent_id = -1
)
);

Inner join base on specific condition

There are 3 tables Brand,Product and BrandProduct respectively.Table has following structure.
Brand : id,BrandName
Product : id,ProductName
BrandProduct :id,Brandid,Productid,Prize,RetailerName
I want to display the name of product,prize and retailername.This is my query.
select ProductName,Prize,RetailerName from BrandProduct BP
inner join Product P
on P.id = BP.Productid
When user select Brand,only that's brand record should come.So I changed a query.It is working properly
create proc_sample
#Brandid int = null
as
begin
select ProductName,Prize,RetailerName from BrandProduct BP
inner join Product P
on P.id = BP.Productid
inner join Brand B
on B.id = BP.Brandid
where (#Brandid is null or BP.Brandid= #Brandid)
End
When user will not select brand,join of Brand should not come.Any Idea?I know Dynamic sql come into picture.Any alternative to dynamic sql
No need to join Brand table, because BrandProduct table contains BrandId.
select ProductName,Prize,RetailerName from BrandProduct BP
inner join Product P
on P.id = BP.Productid
where (#Brandid is null or BP.Brandid = #Brandid)