从查询中删除冗余数据

时间:2017-10-18 20:33:06

标签: sql sql-server-2008

我在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 

这是一次糟糕的尝试,希望能够走上正确的方向。这就是我想要实现的目标:

Sample_CategoryList
数据库架构:

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

sample_output

更新 - 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>

2 个答案:

答案 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 |