我在sql server中有以下类别表和示例数据:
CategoryId Category SubCategory Parent Category
1 Electronics N/A
2 Computer Accessories Electronics N/A
3 Hardware Computer Accessories Electronics
4 Software Computer Accessories Electronics
5 Clothing N/A
6 Men Clothing Clothing
7 Women Clothing Clothing
8 Food & Beverages N/A
我试图按照以下方式使用Sql
CategoryId Category SubCategory Parent Category
1 Electronics N/A
2 Computer Accessories Electronics N/A
3 Hardware
4 Software Computer Accessories Electronics
5 Clothing N/A
6 Men
7 Women Clothing
8 Food & Beverages N/A
基本上它是一种层次结构,并试图通过查询来实现。我在项目的一个网页中显示了类别层次结构。因此,我尝试使用以下查询执行自联接并检索冗余名称,但卡住了:
SELECT DISTINCT m.CategoryId,
'Category' = m.CategoryName,
CASE WHEN m.ParentId = (SELECT TOP 1 ParentId FROM Category q
WHERE q.ParentId = k.CategoryId ORDER BY k.CategoryId)
THEN k.CategoryName ELSE '' END AS SubCategory,
'Parent Category' = ISNULL(p.CategoryName, 'N/A')
FROM Category m LEFT JOIN Category k
ON k.CategoryId = m.ParentId
LEFT JOIN Products o ON o.SubCategory = m.CategoryId
LEFT JOIN Category p ON p.CategoryId = o.ParentId
WHERE m.ParentId >= 0
这是一次糟糕的尝试,希望能够走上正确的方向。这就是我想要实现的目标:
CREATE TABLE [dbo].[Products](
[Id] [int] IDENTITY(1,1) PRIMARY KEY,
[ProductId] [nvarchar](20) NULL,
[ProductName] [nvarchar](60) NULL,
[ParentId] [int] NULL,
[SubCategory] [int] NULL,
[Price] [float] NULL,
[Description] [nvarchar](max) NULL,
[Origin] [int] NULL,
[Stock] [int] NULL,
[Status] [bit] NULL
)
INSERT [dbo].[Products] ([Id], [ProductId], [ProductName], [ParentId], [SubCategory], [Price], [Description], [Origin], [Stock], [Status]) VALUES (1, N'1001', N'ERP Solution Package', 1, 4, 60000, N'', 1, 10, 1)
INSERT [dbo].[Products] ([Id], [ProductId], [ProductName], [ParentId], [SubCategory], [Price], [Description], [Origin], [Stock], [Status]) VALUES (2, N'1002', N'Pendrive', 1, 3, 1000, N'', 1, 10, 1)
INSERT [dbo].[Products] ([Id], [ProductId], [ProductName], [ParentId], [SubCategory], [Price], [Description], [Origin], [Stock], [Status]) VALUES (3, N'1003', N'Denim-Men', 5, 6, 1000, N'', 1, 10, 1)
INSERT [dbo].[Products] ([Id], [ProductId], [ProductName], [ParentId], [SubCategory], [Price], [Description], [Origin], [Stock], [Status]) VALUES (4, N'1004', N'Denim-Women', 5, 7, 1000, N'', 1, 20, 1)
CREATE TABLE [dbo].[Category](
[CategoryId] [int] IDENTITY(1,1) PRIMARY KEY,
[CategoryName] [nvarchar](40) NULL,
[ParentId] [int] NULL,
[Description] [nvarchar](max) NULL,
[Status] [bit] NULL
)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (1, N'Electronics', 0, NULL, 1)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (2, N'Computer Accessories', 1, NULL, 1)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (3, N'Hardware', 2, NULL, 1)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (4, N'Software', 2, NULL, 1)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (5, N'Clothing', 0, NULL, 1)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (6, N'Men', 5, NULL, 1)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (7, N'Women', 5, NULL, 1)
INSERT [dbo].[Category] ([CategoryId], [CategoryName], [ParentId], [Description], [Status]) VALUES (8, N'Food & Beverages', 0, NULL, 1)
主要查询:
SELECT m.CategoryId, 'Category' = m.CategoryName, 'Product' = ISNULL(o.ProductName, 'N/A'),
'Sub-Category' = ISNULL(k.CategoryName, 'N/A'), 'Parent Category' = ISNULL(p.CategoryName, 'N/A')
FROM Category m LEFT JOIN Category k
ON k.CategoryId = m.ParentId
LEFT JOIN Products o ON o.SubCategory = m.CategoryId
LEFT JOIN Category p ON p.CategoryId = o.ParentId
WHERE m.ParentId >= 0
更新 - 1 :
更新 - 2 - 我尝试使用以下方法处理用户界面中的层次结构:
<div class="panel panel-default">
@foreach (var item2 in lst.GroupBy(p => p.ParentCategory))
{
<div class="panel-heading">
<h4 class="panel-title">
@if (item2.Key != "N/A")
{
<a data-toggle="collapse" data-parent="#accordian" href="#@item2.Key">
@item2.Key
<span class="badge pull-right"><i class="fa fa-plus"></i></span>
</a>
}
</h4>
</div>
<div id="@item2.Key" class="panel-collapse collapse">
<div class="panel-body">
<ul>
@foreach (var item in lst.Where(p => p.ParentCategory == item2.Key).GroupBy(m => m.SubCategory, (key, c) => c.FirstOrDefault()))
{
@item.SubCategory
<br />
}
</ul>
</div>
</div>
}
</div>
答案 0 :(得分:2)
这会让你得到结果,但我不认为这是你想要的。
SELECT CategoryId,
Category,
CASE WHEN [Parent Category] = 'N/A' SubCategory
WHEN [Parent Category] <> 'N/A' AND RN > 1 THEN SubCategory ELSE NULL END AS SubCategory,
CASE WHEN [Parent Category] = 'N/A' [Parent Category]
WHEN [Parent Category] <> 'N/A' AND RN > 1 THEN [Parent Category] ELSE NULL END AS SubCategory,
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY SubCategory, [Parent Category] ORDER BY CategoryId ASC) AS RN
FROM table_name_you_did_not_tell_us
)
答案 1 :(得分:2)
<强> SQL DEMO 强>
WITH cte as (
SELECT * ,
ROW_NUMBER() OVER
(partition by [SubCategory], [Parent Category] ORDER BY [Parent Category]) as rn
FROM Table1
)
SELECT [CategoryId], [Category],
CASE WHEN [Parent Category] = 'N/A' THEN [SubCategory]
WHEN [rn] = 1 THEN [SubCategory]
ELSE NULL
END as [SubCategory],
CASE WHEN [Parent Category] = 'N/A' THEN [Parent Category]
WHEN [rn] = 1 THEN [Parent Category]
ELSE NULL
END as [Parent Category]
FROM cte
ORDER BY [CategoryId]
<强>输出强>
| CategoryId | Category | SubCategory | Parent Category |
|------------|----------------------|----------------------|-----------------|
| 1 | Electronics | (null) | N/A |
| 2 | Computer Accessories | Electronics | N/A |
| 3 | Hardware | Computer Accessories | Electronics |
| 4 | Software | (null) | (null) |
| 5 | Clothing | (null) | N/A |
| 6 | Men | Clothing | Clothing |
| 7 | Women | (null) | (null) |
| 8 | Food & Beverages | (null) | N/A |