【问题标题】:SQL Server INNER JOIN with hierarchyid带有hierarchyid的SQL Server INNER JOIN
【发布时间】:2012-04-26 08:16:44
【问题描述】:

我有两张表,一张表是 items 容器,其中包含与产品相关的所有数据。另一个表用于类别,其中数据使用层次结构进行组织。
查询的目标是从所选类别向下列出与类别匹配的项目。

例子:

CatID: 3, Parent: Root, Name: Computers  
CatID: 4, Parent: 3, Name: Laptops  
CatID: 5, Parent: 3, Name: Monitors  
CatID: 6, Parent: 3, Name: Printers  
CatID: 7, Parent: 6, Name: Laser  
CatID: 8, Parent: 6, Name: Ink  
CatID: 9, Parent: 6, Name: Multifunction  
CatID: 10, Parent: 6, Name: Copier  

如果CatID选为3,则显示所有电脑产品,但如果CatID选6,则只显示打印机(CatID为7、8、9、10的项目)

我对层次结构 ID 比较陌生,我对如何处理此查询一无所知。

感谢所有贡献的人。

卡洛斯

两个表的架构 这个想法是将 mz_category 连接到 ic_item_cat,因此查询可以列出给定类别的所有项目,也可以列出所有子类别。这适用于特殊的“自制”树视图,其中所有类别都根据层次结构显示;当用户单击一个类别时,它会显示属于该类别的所有项目以及属于子类别的所有项目。希望你能明白。

/****** Object:  Table [dbo].[mz_category]    Script Date: 04/26/2012 19:14:34 ******/
SET ARITHABORT ON
GO
SET CONCAT_NULL_YIELDS_NULL ON
GO
SET ANSI_NULLS ON
GO
SET ANSI_PADDING ON
GO
SET ANSI_WARNINGS ON
GO
SET NUMERIC_ROUNDABORT OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
SET ARITHABORT ON
GO
/****** Categories Table ******/
CREATE TABLE [dbo].[mz_category](
    [CatNode] [hierarchyid] NOT NULL,
    [CatLevel]  AS ([CatNode].[GetLevel]()),
    [CatID] [int] NOT NULL,
    [CatName] [varchar](80) NOT NULL,
    [SectorId] [varchar](2) NULL,
    [CatIcon] [varchar](255) NULL,
    [oldCat] [varchar](8) NULL,
PRIMARY KEY CLUSTERED 
(
    [CatNode] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED 
(
    [CatID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[ic_item_cat]    Script Date: 04/26/2012 19:14:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
/****** Items Table ******/
CREATE TABLE [dbo].[ic_item_cat](
    [item_code] [varchar](25) NOT NULL,
    [item_description] [varchar](80) NULL,
    [item_sector] [varchar](2) NULL,
    [item_line] [varchar](2) NULL,
    [item_reference] [varchar](50) NULL,
    [item_upcean] [varchar](50) NULL,
    [item_category] [int] NULL,
    [item_brand] [varchar](8) NULL,
    [item_cost] [decimal](12, 4) NULL,
    [item_price1] [decimal](12, 4) NULL,
    [item_price2] [decimal](12, 4) NULL,
    [item_price3] [decimal](12, 4) NULL,
    [item_webprice] [decimal](12, 4) NULL,
    [item_dprice1] [decimal](12, 4) NULL,
    [item_dprice2] [decimal](12, 4) NULL,
    [item_dprice3] [decimal](12, 4) NULL,
    [item_lastcost] [decimal](12, 4) NULL,
    [item_lastcostdate] [datetime] NULL,
    [item_lastqtyout] [decimal](12, 4) NULL,
    [item_lastqtyoutdate] [datetime] NULL,
    [item_lastqtyin] [decimal](12, 4) NULL,
    [item_lastqtyindate] [datetime] NULL,
    [item_additionaldesc] [varchar](max) NULL,
    [item_weight] [decimal](12, 4) NULL,
    [item_weight_measure] [varchar](2) NULL,
    [item_width] [decimal](12, 4) NULL,
    [item_width_measure] [varchar](2) NULL,
    [item_length] [decimal](12, 4) NULL,
    [item_length_measure] [varchar](2) NULL,
    [item_height] [decimal](12, 4) NULL,
    [item_height_measure] [varchar](2) NULL,
    [item_whpackdesc] [varchar](80) NULL,
    [item_salespackdesc] [varchar](80) NULL,
    [item_purchpackdesc] [varchar](80) NULL,
    [item_salespackconv] [decimal](12, 4) NULL,
    [item_purchpackconv] [decimal](12, 4) NULL,
    [item_warranty] [varchar](2) NULL,
    [item_delivtime] [varchar](2) NULL,
    [item_rating] [int] NULL,
    [item_vat] [varchar](2) NULL,
    [item_status] [int] NULL,
    [item_avgleadtime] [int] NULL,
    [web_flag] [bit] NULL,
    [partner_id] [varchar](25) NULL,
    [unique_id] [uniqueidentifier] NOT NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO

【问题讨论】:

    标签: sql hierarchyid


    【解决方案1】:

    这样的东西会起作用吗?

    DECLARE @CatNode hierarchyid;
    SET @CatNode = (
        SELECT CatNode from mz_category
        WHERE CatID = @CatID
      );
    SELECT * FROM Items
    WHERE CatID IN (
      SELECT  CatID
      FROM    mz_category
      WHERE   CatNode.IsDescendantOf(@CatNode) = 1
    );
    

    【讨论】:

    • 不幸的是,这不好。它显示项目表中的所有行。尽管必须更改代码,除非您对此有进一步的解释。 @mz_category 没有声明,我猜它是表名 mz-category 所以我删除了@。
    • 糟糕。应该是 IsDescendantOf(@CatNode)。已编辑。
    • 效果很好!非常感谢,伙计。现在是我继续学习和独自飞行的时候了。
    • 还要感谢所有提出建议的人。
    • +1 很好,我认为 hierarchyid 仅在即将推出的 Denali 版本中可用...
    【解决方案2】:

    您可以使用CTE

    • 选择起始记录
    • 在递归部分获取这些起始记录的子项

    SQL 语句

    ;WITH q AS (
      SELECT  CatID, Parent, Name
      FROM    YourTable
      WHERE   CatID = 3
      UNION ALL
      SELECT  t.CatID, t.Parent, t.Name
      FROM    q
              INNER JOIN YourTable t ON t.Parent = q.CatID
    )
    SELECT  *
    FROM    q
    

    【讨论】:

    • 感谢您的意见。也许我在帖子中还不够清楚。我想要实现的是查询 ic_item 表(项目)列出了属于某个类别的所有项目以及该类别的所有子项。我知道如何使用 IsDescendantOf 构建查询以便从节点中获取所有子节点,但我不知道如何将其加入 items 表。
    • 对不起,我不知道你需要什么。在我们参与 20 个问题的游戏之前,您应该至少发布架构。理想的做法是包含一些测试数据和预期输出。
    • 发布了架构并简要说明了我想要实现的目标
    【解决方案3】:
    DECLARE @CatID hierarchyid = '/6/';
    
    WITH RootCategory AS (
        SELECT  CatID,
                Parent,
                Name
        FROM    Category
        WHERE   CatID = @CatID
    
        UNION ALL
    
        SELECT      C.CatID,
                    C.Parent,
                    C.Name
        FROM        Category C
        INNER JOIN  RootCategory R ON C.Parent = R.CatID
    )
    SELECT  *
    FROM    RootCategory
    

    【讨论】:

    • 感谢您的意见。也许我在帖子中还不够清楚。我想要实现的是查询 ic_item 表(项目)列出了属于某个类别的所有项目以及该类别的所有子项。我知道如何使用 IsDescendantOf 构建查询以便从节点中获取所有子节点,但我不知道如何将其加入 items 表。
    • 您能发布您的 Items 表的架构吗?如果没有这些信息,我无法编写该查询。
    • 发布了架构并简要说明了我想要实现的目标
    猜你喜欢
    • 2012-04-02
    • 2012-01-25
    • 2011-07-11
    • 2012-01-23
    • 1970-01-01
    • 2015-10-31
    • 2016-12-23
    • 1970-01-01
    • 2018-06-26
    相关资源
    最近更新 更多