SQL - Recursively finding count in another table - sql

I have a table which has both category and subcategory such as this :
CategoryID CategoryName ParentCategoryID
1 CatA NULL
2 CatA1 1
3 CatA2 1
4 CatA3 1
5 CatB NULL
6 CatB1 5
7 CatC NULL
8 CatC1 7
I have another table where I have mappings
MappingID CategoryID ItemID
1 2 1
2 3 1
3 6 2
4 8 3
5 2 3
6 3 4
7 4 4
8 2 3
9 3 4
10 2 2
11 2 2
12 2 2
13 2 3
14 2 1
I need a result set where count of all items per category is displayed such as :
Category No. of Items
1 12
5 1
7 1
Could you someone guide me with this?
I have tried using a CTE :
WITH CTE (CategoryID, CategoryName, ParentID, CategoryParentName)
AS
(
SELECT CategoryID,
CategoryName,
ParentCategoryID,
CategoryName AS CategoryParentName
FROM [dbo].[Category]
WHERE ParentCategoryID IS NULL
AND IsDeleted = 0
UNION ALL
SELECT garages.CategoryID,
garages.CategoryName,
garages.ParentCategoryID,
traces.CategoryName AS CategoryParentName
FROM [dbo].[Category] AS garages
INNER JOIN CTE AS traces ON traces.CategoryID= garages.ParentCategoryID
)
SELECT gr.CategoryID, COUNT(map.CategoryID) AS Total
FROM CTE gr
INNER JOIN [dbo].[CategoryMapping] map ON gr.CategoryID = map.CategoryID
GROUP BY gr.CategoryID

If there are just two levels of categories than there is no need for recursive query
select coalesce(c.ParentCategoryID, c.CategoryID), count(*)
from Category c
join CategoryMapping m on c.CategoryID = m.CategoryID
group by coalesce(c.ParentCategoryID, c.CategoryID)
Obviously, categories without mapping won't be there.

Related

Get max record for each group of records, link multiple tables

I seek to find the maximum timestamp (ob.create_ts) for each group of marketid's (ob.marketid), joining tables obe (ob.orderbookid = obe.orderbookid) and market (ob.marketid = m.marketid). Although there are a number of solutions posted like this for a single table, when I join multiple tables, I get redundant results. Sample table and desired results below:
table: ob
orderbookid
marketid
create_ts
1
1
1664635255298
2
1
1664635255299
3
1
1664635255300
4
2
1664635255301
5
2
1664635255302
6
2
1664635255303
table: obe
orderbookentryid
orderbookid
entryname
1
1
'entry-1'
2
1
'entry-2'
3
1
'entry-3'
4
2
'entry-4'
5
2
'entry-5'
6
3
'entry-6'
7
3
'entry-7'
8
4
'entry-8'
9
5
'entry-9'
10
6
'entry-10'
table: m
marketid
marketname
1
'market-1'
2
'market-2'
desired results
ob.orderbookid
ob.marketid
obe.orderbookentryid
obe.entryname
m.marketname
3
1
6
'entry-6'
'market-1'
3
1
7
'entry-7'
'market-1'
6
2
10
'entry-10'
'market-2'
Use ROW_NUMBER() to get a properly filtered ob table. Then JOIN the other tables onto that!
WITH
ob_filtered AS (
SELECT
orderbookid,
marketid
FROM
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY
marketid
ORDER BY
create_ts DESC
) AS create_ts_rownumber
FROM
ob
) ob_with_rownumber
WHERE
create_ts_rownumber = 1
)
SELECT
ob_filtered.orderbookid,
ob_filtered.marketid,
obe.orderbookentryid,
obe.entryname,
m.marketname
FROM
ob_filtered
JOIN m
ON m.marketid = ob_filtered.marketid
JOIN obe
ON ob_filtered.orderbookid = obe.orderbookid
;

using sql join on three tables

I have 3 tables which maintains stock entries for each products/items. These three tables like below :
Table : ItemStock (to maintain remaining stock of each item)
Id ItemId OpgQty BranchID CurrentStock
1 7 0 1 8
2 7 0 2 3
3 6 0 1 2
4 6 0 2 0
Table : ItemPurchase (StockIn)
Id ItemId Qty BranchID
1 7 5 1
2 7 4 2
3 7 6 1
4 7 2 2
5 6 4 1
6 6 2 2
7 6 2 1
Table : ItemSale (StockOut)
Id ItemId Qty BranchID
1 7 2 1
2 7 3 2
3 7 1 1
4 6 4 1
5 6 2 2
Desired Output (based on sql queries)
I want to have result like below : (part of report)
Id ItemId OpgQty BranchId StockIn StockOut CurrentStock
1 7 0 1 11 3 8
2 7 0 2 6 3 3
3 6 0 1 6 4 2
4 6 0 2 2 2 0
I was trying to get the desired result but was not able to do so. Please help!!!
try this;
select
m.Id,
m.ItemId,
m.OpgQty,
m.BranchID,
si.StockIn,
m.CurrentStock-si.StockIn StockOut,
m.CurrentStock
from
ItemStock m
inner join
(
select
ItemId,BranchId,sum(Qty) as StockIn
from
ItemPurchase
group by ItemId,BranchId
) si on si.ItemId=m.ItemId and si.BranchId=m.BranchId
A very simple query that gives the desired result is :
select *,
(select sum(Qty)
from ItemPurchase
where ItemPurchase.ItemId = ItemStock.ItemId and
ItemPurchase.BranchId = ItemStock.BranchId) as StockIn,
(select sum(Qty)
from ItemSale
where ItemSale.ItemId = ItemStock.ItemId and
ItemSale.BranchId = ItemStock.BranchId) as StockOut
from ItemStock
Two subqueries with group by and aggregation will get what you want.
select
s.*,
coalesce([ip].StockIn, 0) as StockIn, -- In case of no records in ItemPurchase or ItemSale, coalesce is neccessary.
coalesce([is].StockOut, 0) as StockOut
from ItemStock s
left join (
select sum(Qty) as StockIn, ItemId, BranchId
from ItemPurchase
group by ItemId, BranchId
) [ip] on s.ItemId = [ip].ItemId and s.BranchId = [ip].BranchId
left join (
select sum(Qty) as StockOut, ItemId, BranchId
from ItemSale
group by ItemId, BranchId
) [is] on s.ItemId = [is].ItemId and s.BranchId = [is].BranchId
See demo in sqlfiddle.
Please
Try This ... I hope you consider this too.

Parent child hierarchy in sql server

I have the following requirement,
Input
CID ParentID
1 10
2 1
3 1
4 2
5 2
6 2
7 2
8 4
9 4
10 NULL
20 25
30 38
15 51
17 71
when I pass child value as 4 following is my desired output:
Desired Output:
CID ParentID
2 4
1 2
10 1
NULL 10
4 2
4 8
2 4
2 5
2 6
1 3
2 7
    
Please help! Thanks in advance.
Your explanation and your data don't match. I think the row (4, 2) in the results should be (4,9). If I'm correct, then this should do what you want:
with Parents(lvl, CID, ParentID) as (
select 0, ParentID, CID
from T
where CID = 4
union all
select lvl+1, T.ParentID, T.CID
from T join Parents
on T.CID = Parents.CID
)
select CID, ParentID
from Parents
union all
select T.ParentID, T.CID
from T join Parents
on Parents.ParentID = T.ParentID;
SQL fiddle here.

Distinct rows based on One column in multi union

I am working to build a hierarchical menu which is based on 4 table. after doing research the only solution i can think of is to do it with the UNION so far i am close but still i don't have the desired result.
4 Table which i am using are
Page Table with PageID as PK (Which holds actual pages for cms)
Article Table with PageID as FK (Which has article)
Article Category Table with PageID as FK (this table has article category)
Magazine Table with PageID as FK (Magazine table holds magazine information)
I had to make some changes to my database based on some suggestion made to my previous question which is directly related to this question, Previous question has details about database.
I need these columns PID, MENU, Handler,PageLangID, ParentID,IssueID, CatID,MenuPosition
to create my Hierarchical Menu I wrote the below which get me the required column but i am not able run the DISTINCT on Menu so that i will get only Unique Row and based on that result set i can create my menu.
When i try to add DISTINCT (Menu) it generates me syntax error.
I am not sure based on my requirement which is mention in previous question whether this approach is fine or i should take some other approach which is not ambiguous or more professional
QUERY
SELECT PID, MENU, Handler, PageLangID, ParentID,IssueID, CatID, MenuPosition
FROM (
--Pages Table
SELECT PageId AS PID,SUBSTRING(PageName,0,20) AS MENU,SUBSTRING(PageInternalLinkURL,0,24) AS Handler, PageLangID,PageInheritance AS ParentID, 1 AS IssueID, 1 AS CatID,
PageLinkPosition as MenuPosition FROM pg_Pages WHERE PageLangID = 1
UNION
--Article Table
SELECT p.PageID as PID, SUBSTRING(c.ArticleCategoryName,0,20) AS MENU,SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler,LanguageID,p.PageID AS ParentID,IssueID,c.ArticleCategoryID AS CatID,
1 AS MenuPosition FROM art_Articles a JOIN art_Category c ON a.ArticleCategoryID = c.ArticleCategoryID JOIN pg_pages p ON p.PageID = a.PageID WHERE LanguageID =1
UNION
--Article Category Table
SELECT p.PageID AS PID, SUBSTRING(c.ArticleCategoryName,0,20) AS MENU,SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler, LangID,p.PageID,1, ArticleCategoryID,
1 AS MenuPosition FROM art_Category c JOIN pg_Pages p ON c.PageID = p.PageID WHERE LangID =1
UNION
--Magazine Table
SELECT p.PageID AS PID, CAST(IssueCode AS varchar(10)),SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler,LangID,p.PageID AS ParentID, m.IssueID AS IssueID, 1,
1 AS MenuPosition FROM Magazine m JOIN pg_pages p ON m.PageID = p.PageID WHERE LangID =1
) AS T WHERE T.PageLangID = 1 ORDER BY MenuPosition
OUTPUT
PID MENU Handler PageLangID ParentID IssueID CatID MenuPosition
----------- -------------------- ------------------------ ----------- ----------- ----------- ----------- ------------
5 Book Review Articles.aspx 1 5 5 18 1
5 Business Articles.aspx 1 5 5 16 1
5 Group News Articles.aspx 1 5 5 6 1
5 Infrastructure Articles.aspx 1 5 5 17 1
5 Politics Articles.aspx 1 5 1 1 1
5 Politics Articles.aspx 1 5 3 1 1
5 Politics Articles.aspx 1 5 4 1 1
5 Politics Articles.aspx 1 5 5 1 1
6 Book Review Article-Category.aspx 1 6 1 18 1
6 Business Article-Category.aspx 1 6 1 16 1
6 Chairman's Message Article-Category.aspx 1 6 1 9 1
6 Culture Article-Category.aspx 1 6 1 3 1
6 Economy Article-Category.aspx 1 6 1 2 1
6 Editorial Message Article-Category.aspx 1 6 1 8 1
6 Finance Article-Category.aspx 1 6 1 19 1
6 Group News Article-Category.aspx 1 6 1 6 1
6 Habtoor Leighton Gr Article-Category.aspx 1 6 1 5 1
6 Infrastructure Article-Category.aspx 1 6 1 17 1
6 Lifestyle Article-Category.aspx 1 6 1 20 1
6 People Article-Category.aspx 1 6 1 7 1
6 Politics Article-Category.aspx 1 6 1 1 1
6 Sports Article-Category.aspx 1 6 1 4 1
12 102 Default.aspx 1 12 3 1 1
12 103 Default.aspx 1 12 4 1 1
12 106 Default.aspx 1 12 1 1 1
12 109 Default.aspx 1 12 5 1 1
1 Home Default.aspx 1 0 1 1 10
11 Video Videos.aspx 1 10 1 1 10
2 About Us Page.aspx 1 0 1 1 20
5 Articles Articles.aspx 1 0 1 1 20
6 Categories Article-Category.aspx 1 0 1 1 25
3 News News.aspx 1 0 1 1 30
12 Archive Default.aspx 1 0 1 1 40
10 Multimedia Multimedia.aspx 1 0 1 1 60
You have used order by in the outer select statement.
As order by not working with the distinct statement,
So, Do the DISTINCT in a subselect and the ORDER BY in the outer select.
Hope this will be helpful to solve out your problem.
You need DISTINCT on all SELECT statements
SELECT DISTINCT PID, MENU, Handler, PageLangID, ParentID,IssueID, CatID, MenuPosition
...

SQL query to show most ordered product

I have this table structure
Product
product_id (PK)
name
Order_Detail
order_detail_id
product_id
quantity
Example data
Product :
1 product1
2 product2
3 product3
4 product4
5 product5
Order_Detail :
1 3 2
2 3 1
3 3 1
4 2 1
5 2 1
6 1 1
7 4 1
8 5 1
9 1 1
10 2 1
11 3 1
Please help me to get top 3 ordered product based on how many times the product ordered ?
I think this migth work:
SELECT p.`product_id`, p.`name`, SUM(o.`quantity`) AS quantity
FROM `Order_Detail` AS o
INNER JOIN `Product` AS p
ON o.`product_id` = p.`product_id`
GROUP BY o.`product_id`
ORDER BY SUM(o.`quantity`) DESC, p.`name` ASC
LIMIT 3