Sql Recursive Function only show nods that have specifik relation - sql-server

I have a Link structure table with ID and parentID.
ID, Parent, name
1,1
2,1
3,2
4,3
5,3
To this table I have a structure_article relation table
in this table I have relation between a Link and a article.
struture_article
structid, articleID
4,1000
4,1001
5,1002
Every article in that table have a supplier.
Now i am trying to create a recursive function that creates the tree
nods if i pick a specific supplier.
Article table
ArticleID, SUPPLIER ID
1000,1
1001,2
1002,2
If I pick articles with supplier 1 then I want the function to show me the tree structure that have articles from that supplier.
I have 20 suppliers and 300 links in the DB now i want only to show articles from the suppliers i pick. I don want any empty nods.
Is this even possible do create with a recursive function in Sql Server version 2008?
I tyied wiht this code the problem is that i get only nods that have articles connected
WITH a
AS (SELECT *
FROM structure
WHERE parent = 125
UNION ALL
SELECT m.*
FROM structure m
JOIN a
ON m.parent = a.internidstructure)
SELECT *
FROM a
WHERE internidstructure IN (SELECT DISTINCT( internidstructure )
FROM dbo.articles
INNER JOIN dbo.structure_article
ON dbo.articles.internidarticle =
dbo.structure_article.internidarticle
WHERE ( dbo.articles.internidsupplier IN (SELECT
internidsupplier
FROM site_sup
WHERE
internidsite = 1) ))
ORDER BY parent,
sortno

Try using a left join instead of an inner join.

I'm not sure to have understood your need but if you want to have a new tree table without nodes not linked to a supplier, this query can work.
WITH A AS
(
SELECT S.ID as ID, S.Parent as Parent, 1 as art_linked
FROM structure S
INNER JOIN dbo.structure_article SA
ON S.ID = SA.structid
INNER JOIN Article AR
ON AR.ArticleID = SA.ArticleID
WHERE AR.SupplierID = 1
UNION ALL
SELECT S.ID, S.Parent, 0
FROM structure S
INNER JOIN A
ON A.parent = S.ID
WHERE S.ID <> S.Parent
)
SELECT A.ID, A.Parent, MAX(A.art_linked)
FROM A
GROUP BY A.ID, A.Parent

Related

sql server - How to Get all distinct value in group by column from two table and count from another table for each value

I have 3 tables in that 2 tables are master table and 3rd is transaction table. i need to get count from transaction table for each value in other two table without loosing rows in mater table
i need result like below
Table layout for understanding
This is the code i have tried,
select s.status_name, e.machine_group_name, qty = COALESCE(COUNT(e.id),0)
from tbl_status s
left outer JOIN tbl_transaction as e ON e.status_name = s.status_name
group by e.machine_group_name, s.status_name
This is solution i have figured:
select m.machine_group_name, s.status_name, qty = COUNT(e.id) from
tbl_machine_group as m
cross join tbl_status as s
left outer join tbl_transaction as e on e.status_name = s.status_name
and e.machine_group_name = m.machine_group_name
group by m.machine_group_name, s.status_name
order by machine_group_name
select
MC_Group_Name
,Status_Name
,count(1) as [Count of Transaction]
from
tbl_Transaction tbl_3
left join tbl_Machine_Group tbl_1
on tbl_3.MC_Group_Name = tbl_1.MC_Group_Name
left join tbl_Status tbl_2
on tbl_3.Status_Name = tbl_2.Status_Name
group by
MC_Group_Name
,Status_Name

Create and execute stored procedure in SQL Server

I have four tables:
dbo.Projects (id, ProjectName, Areas, PaymentSystem, Districts.id, purpose.id, types.id, etc)
dbo.Districts(id, DistrictsName)
dbo.Purpose (id, PurposeName) - has residential & commercial
dbo.Types (id, typName)
I want to select DistrictsName where PurposeName = 'residential'
I tried this procedure :
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'
this is the result from this procedure:
ID DistrictsName PurposeName
1 District1 residential
2 District1 residential
3 District2 residential
4 District2 residential
i want display the DistrictsName without duplicate or with different values , i a have also one more project per district in projects records . this what i want to display :
ID DistrictsName PurposeName
1 District1 residential
2 District2 residential
how i get this result ,
any help is appreciated.
Why do people use stored procedures when views are much more appropriate? I have never understood this. It seems peculiar to SQL Server users.
In any case, you can do what you want with aggregation:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as id,
d.DistrictName, p.PurposeName
FROM dbo.Projects pr INNER JOIN
dbo.Purpose pu
ON pr.PurposeID = pu.ID INNER JOIN
dbo.Districts d
ON pr.DistrictID = d.ID
WHERE pu.PurposeName = N'Residential'
GROUP BY d.DistrictName, p.PurposeName;
The use of table aliases makes the query much easier to write and to read.
In addition, I don't understand the id column being output. Why would you want to construct a new id? In any case, that is what your data suggests.
Use DISTINCT statement for removing the duplicates:
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT DISTINCT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'

Recursive query SQL Server not working as expected

thanks in advance for you help. I'm still quite new to MS SQL db but I was wondering why my recursive query for MSSQL below does not return the value i'm expecting. I've done my research and at the bottom is the code I came up with. Lets say I have the following table...
CategoryID ParentID SomeName
1 0 hmm
2 0 err
3 0 woo
4 3 ppp
5 4 ttt
I'm expecting the query below to return 3 4 5. I basically wanted to get the list of category id's heirarchy below it self inclusive based on the category id I pass in the recursive query. Thanks for you assistance.
GO
WITH RecursiveQuery (CategoryID)
AS
(
-- Anchor member definition
SELECT a.CategoryID
FROM [SomeDB].[dbo].[SomeTable] AS a
WHERE a.ParentID = CategoryID
UNION ALL
-- Recursive member definition
SELECT b.CategoryID
FROM [SomeDB].[dbo].[SomeTable] AS b
INNER JOIN RecursiveQuery AS d
ON d.CategoryID = b.ParentID
)
-- Statement that executes the CTE
SELECT o.CategoryID
FROM [SomeDB].[dbo].[SomeTable] AS o
INNER JOIN RecursiveQuery AS d
ON d.CategoryID = 3
GO
If you want tree from specific root:
DECLARE #rootCatID int = 3
;WITH LessonsTree (CatID)
AS
(
SELECT a.CategoryID
FROM [EducationDatabase].[dbo].[LessonCategory] AS a
WHERE a.CategoryID = #rootCatID ---<<<
UNION ALL
SELECT b.CategoryID
FROM LessonsTree as t
INNER JOIN [EducationDatabase].[dbo].[LessonCategory] AS b
ON b.ParentID = t.CatID
)
SELECT o.*
FROM LessonsTree t
INNER JOIN [EducationDatabase].[dbo].[LessonCategory] AS o
ON o.CategoryID = t.CatID
As stated in the comments, the anchor isn't restricted. Easiest solution is to add the criterium in the anchor
with RecursiveQuery (theID)
AS
(
SELECT a.ParentID --root id=parentid to include it and to prevent an extra trip to LessonCategory afterwards
FROM [LessonCategory] AS a
WHERE a.ParentID = 3 --restriction here
UNION ALL
SELECT b.CategoryID
FROM [LessonCategory] AS b
INNER JOIN RecursiveQuery AS d
ON d.theID = b.ParentID
)
SELECT* from RecursiveQuery
Another option is to have the recursive query be general (no restricted anchor) and have it keep the rootid as well. Then the query on the cte can restrict on the rootid (the first option is probably better, this second one is mainly suitable if you are created some sort of root-view)
with RecursiveQuery
AS
(
SELECT a.ParentID theID, a.ParentID RootID
FROM [LessonCategory] AS a
UNION ALL
SELECT b.CategoryID, d.RootID
FROM [LessonCategory] AS b
INNER JOIN RecursiveQuery AS d
ON d.theID = b.ParentID
)
SELECT theID from RecursiveQuery where RootID = 3

How to select distinct records from tables which are inner join with each other

I have 3 Tables
News (News_ID,Title,Article,Attatchment,Publish_Status,Sort_Order,Date,Read_Status)
Category (Category_ID,Category_Name,Parent)
News_Category(ID,News_ID,Category_ID)
I want to select top 4 records from table News whose Category_ID in News_Category table is 12 and also whose Parent in category table is 12.
I have used following query:-
SELECT DISTINCT
News.News_ID, News.Title, News.Article, News.Attatchment, News.Publish_Status, News.Sort_Order, News.Read_Status, News.[Date]
,News_Category.ID
,Category.Category_Name
FROM News
INNER JOIN News_Category ON News_Category.News_ID = News.News_ID
INNER JOIN Category ON News_Category.Category = Category.Category_ID
WHERE News_Category.Category in
( select Category_ID
from Category
where Category_ID=12
union
select Category_ID
from Category
where Parent=12 )
ORDER BY News.News_ID DESC
But when i insert a single news in two Category having Parent=12 then it is showing duplicate data.Please help me.
Leaving out the News_Category.ID should fix it I believe.
SELECT DISTINCT
News.News_ID, News.Title, News.Article, News.Attatchment, News.Publish_Status, News.Sort_Order, News.Read_Status, News.[Date]
,Category.Category_Name
FROM News
INNER JOIN News_Category ON News_Category.News_ID = News.News_ID
INNER JOIN Category ON News_Category.Category = Category.Category_ID
WHERE News_Category.Category in
( select Category_ID
from Category
where Category_ID=12
or Parent=12 )
ORDER BY News.News_ID DESC

SQL Select random from multiple table and order by specific criteria on one table

I need to select a random record from 3 tables and ensure I am ordering by photoOrder
Select TOP 1(a.id), a.mls_number, a.parcel_name, a.property_type, a.ownership_type, b.filename, b.photoOrder, c.county_Name
From property as a
Inner JOIN
listingPhotos as b on a.id = b.ListingID
LEFT JOIN
counties as C on a.county_name = c.id
WHERE a.isCommercial = 'True'
Order By NEWID()
So this query works, but I need to ensure that the b.filename record is ordered by b.photoOrder and thus the b.photoOrder should always be 1.
The b table (listing photos) has multiple photo files per property and I need to only select the photo that is 1st in the photo order.
Thanks
You could subquery your listingPhotos table and limit to WHERE PhotoOrder = 1:
Select TOP 1(a.id), a.mls_number, a.parcel_name, a.property_type, a.ownership_type, b.filename, b.photoOrder, c.county_Name
From property as a
Inner JOIN
(SELECT ListingID , filename, PhotoOrder FROM listingPhotos WHERE PhotoORder = 1
) as b on a.id = b.ListingID
LEFT JOIN
counties as C on a.county_name = c.id
WHERE a.isCommercial = 'True'
Order By NEWID()

Resources