如何为困难的连接获得基于集合的解决方案

时间:2013-04-30 07:59:40

标签: sql

我有一张带有产品清单的表格 我有一张包含商家名单的表格 我有一张带有仓库清单的桌子。

我有一个WarehouseMerchant表,因此仓库可以分配许多商家。

我有一个WarehouseMerchantProduct表,因此商家可以将其产品列在仓库中

我有一个可以链接2个商家的商家链接表

MerchantLinkID      int 
MasterMerchantID    int 
LinkedMerchantID    int 
PreferenceOrder     int 

我需要做的是传递产品ID并获得可以出售它的商家产品的唯一列表。

4条规则

  1. 如果商家有销售产品的关联商家,则不显示关联的商家产品
  2. 如果商家有链接商家也销售产品,但主商家库存水平为0,则只显示关联商家产品
  3. 如果商家有多个仓库库存,那么仓库商品表中会有一个首选订单来选择使用哪个仓库
  4. 每个商家应该只有一个产品才能全部运行
  5. 我一直绞尽脑汁试图找出解决方案。我正沿着游标的路走下去,但它变得有点笨拙。然后我被赋予了4条规则作为要求,将我送回绘图板。

    如果有人能想到一个快速简单的基于设置的解决方案,那么我很乐意听到它。

    以下是创建表和关系的脚本

     CREATE TABLE [dbo].[MW_Merchant](
        [MerchantID] [int] IDENTITY(1,1) NOT NULL,
        [MerchantName] [nvarchar](150) NOT NULL,
        [MerchantCode] [char](10) NOT NULL,
        [Active] [bit] NOT NULL,
     CONSTRAINT [PK_Merchant] PRIMARY KEY CLUSTERED 
    (
        [MerchantID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
     CONSTRAINT [ucMerchantCode] UNIQUE NONCLUSTERED 
    (
        [MerchantCode] 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].[MW_Warehouse]    Script Date: 04/30/2013 09:17:39 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    SET ANSI_PADDING ON
    GO
    CREATE TABLE [dbo].[MW_Warehouse](
        [WarehouseID] [int] IDENTITY(1,1) NOT NULL,
        [WarehouseName] [nvarchar](150) NOT NULL,
        [WarehouseCode] [varchar](10) NOT NULL,
        [Active] [bit] NOT NULL,
     CONSTRAINT [PK_Warehouse] PRIMARY KEY CLUSTERED 
    (
        [WarehouseID] 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].[MW_WarehouseMerchantProduct]    Script Date: 04/30/2013 09:17:39 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    SET ANSI_PADDING ON
    GO
    CREATE TABLE [dbo].[MW_WarehouseMerchantProduct](
        [WarehouseMerchantProductID] [int] IDENTITY(1,1) NOT NULL,
        [WarehouseID] [int] NOT NULL,
        [MerchantID] [int] NOT NULL,
        [ProductCode] [varchar](30) NOT NULL,
        [StockLevel] [int] NOT NULL,
        [Active] [bit] NOT NULL,
        [PriorityOrder] [int] NOT NULL,
     CONSTRAINT [PK_MW_WarehouseProduct] PRIMARY KEY CLUSTERED 
    (
        [WarehouseMerchantProductID] 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].[MW_WarehouseMerchant]    Script Date: 04/30/2013 09:17:39 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[MW_WarehouseMerchant](
        [WarehouseMerchantID] [int] IDENTITY(1,1) NOT NULL,
        [WarehouseID] [int] NOT NULL,
        [MerchantID] [int] NOT NULL,
        [Active] [bit] NOT NULL,
        [PreferenceOrder] [int] NOT NULL,
     CONSTRAINT [PK_MW_WarehouseMerchant] PRIMARY KEY CLUSTERED 
    (
        [WarehouseMerchantID] 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
    /****** Object:  Table [dbo].[MW_MerchantLink]    Script Date: 04/30/2013 09:17:39 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[MW_MerchantLink](
        [MerchantLinkID] [int] IDENTITY(1,1) NOT NULL,
        [MasterMerchantID] [int] NOT NULL,
        [LinkedMerchantID] [int] NOT NULL,
        [PreferenceOrder] [int] NOT NULL,
     CONSTRAINT [PK_MW_MerchantLink] PRIMARY KEY CLUSTERED 
    (
        [MerchantLinkID] 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
    /****** Object:  Default [DF_MW_WarehouseMerchant_PreferenceOrder]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_WarehouseMerchant] ADD  CONSTRAINT [DF_MW_WarehouseMerchant_PreferenceOrder]  DEFAULT ((10)) FOR [PreferenceOrder]
    GO
    /****** Object:  Default [DF_MW_WarehouseMerchantProduct_PriorityOrder]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_WarehouseMerchantProduct] ADD  CONSTRAINT [DF_MW_WarehouseMerchantProduct_PriorityOrder]  DEFAULT ((10)) FOR [PriorityOrder]
    GO
    /****** Object:  ForeignKey [FK_MW_MerchantLink_MW_Merchant]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_MerchantLink]  WITH CHECK ADD  CONSTRAINT [FK_MW_MerchantLink_MW_Merchant] FOREIGN KEY([MasterMerchantID])
    REFERENCES [dbo].[MW_Merchant] ([MerchantID])
    GO
    ALTER TABLE [dbo].[MW_MerchantLink] CHECK CONSTRAINT [FK_MW_MerchantLink_MW_Merchant]
    GO
    /****** Object:  ForeignKey [FK_MW_MerchantLink_MW_Merchant1]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_MerchantLink]  WITH CHECK ADD  CONSTRAINT [FK_MW_MerchantLink_MW_Merchant1] FOREIGN KEY([LinkedMerchantID])
    REFERENCES [dbo].[MW_Merchant] ([MerchantID])
    GO
    ALTER TABLE [dbo].[MW_MerchantLink] CHECK CONSTRAINT [FK_MW_MerchantLink_MW_Merchant1]
    GO
    /****** Object:  ForeignKey [FK_MW_WarehouseMerchant_MW_Merchant]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_WarehouseMerchant]  WITH CHECK ADD  CONSTRAINT [FK_MW_WarehouseMerchant_MW_Merchant] FOREIGN KEY([MerchantID])
    REFERENCES [dbo].[MW_Merchant] ([MerchantID])
    GO
    ALTER TABLE [dbo].[MW_WarehouseMerchant] CHECK CONSTRAINT [FK_MW_WarehouseMerchant_MW_Merchant]
    GO
    /****** Object:  ForeignKey [FK_MW_WarehouseMerchant_MW_Warehouse]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_WarehouseMerchant]  WITH CHECK ADD  CONSTRAINT [FK_MW_WarehouseMerchant_MW_Warehouse] FOREIGN KEY([WarehouseID])
    REFERENCES [dbo].[MW_Warehouse] ([WarehouseID])
    GO
    ALTER TABLE [dbo].[MW_WarehouseMerchant] CHECK CONSTRAINT [FK_MW_WarehouseMerchant_MW_Warehouse]
    GO
    /****** Object:  ForeignKey [FK_MW_WarehouseMerchantProduct_MW_Merchant]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_WarehouseMerchantProduct]  WITH CHECK ADD  CONSTRAINT [FK_MW_WarehouseMerchantProduct_MW_Merchant] FOREIGN KEY([MerchantID])
    REFERENCES [dbo].[MW_Merchant] ([MerchantID])
    GO
    ALTER TABLE [dbo].[MW_WarehouseMerchantProduct] CHECK CONSTRAINT [FK_MW_WarehouseMerchantProduct_MW_Merchant]
    GO
    /****** Object:  ForeignKey [FK_MW_WarehouseProduct_MW_Warehouse]    Script Date: 04/30/2013 09:17:39 ******/
    ALTER TABLE [dbo].[MW_WarehouseMerchantProduct]  WITH CHECK ADD  CONSTRAINT [FK_MW_WarehouseProduct_MW_Warehouse] FOREIGN KEY([WarehouseID])
    REFERENCES [dbo].[MW_Warehouse] ([WarehouseID])
    GO
    ALTER TABLE [dbo].[MW_WarehouseMerchantProduct] CHECK CONSTRAINT [FK_MW_WarehouseProduct_MW_Warehouse]
    GO
    

    和一些测试数据

    /****** Object:  Table [dbo].[MW_Merchant]    Script Date: 04/30/2013 09:41:50 ******/
    SET IDENTITY_INSERT [dbo].[MW_Merchant] ON
    INSERT [dbo].[MW_Merchant] ([MerchantID], [MerchantName], [MerchantCode], [Active]) VALUES (24, N'Merchant 1', N'MERCH1    ', 1)
    INSERT [dbo].[MW_Merchant] ([MerchantID], [MerchantName], [MerchantCode], [Active]) VALUES (27, N'Merchant 2', N'MERCH2    ', 1)
    INSERT [dbo].[MW_Merchant] ([MerchantID], [MerchantName], [MerchantCode], [Active]) VALUES (28, N'Merchant 3', N'MERCH3    ', 1)
    SET IDENTITY_INSERT [dbo].[MW_Merchant] OFF
    /****** Object:  Table [dbo].[MW_Warehouse]    Script Date: 04/30/2013 09:41:50 ******/
    SET IDENTITY_INSERT [dbo].[MW_Warehouse] ON
    INSERT [dbo].[MW_Warehouse] ([WarehouseID], [WarehouseName], [WarehouseCode], [Active]) VALUES (12, N'Warehouse 1', N'WARE1', 1)
    INSERT [dbo].[MW_Warehouse] ([WarehouseID], [WarehouseName], [WarehouseCode], [Active]) VALUES (13, N'Warehouse 2', N'WARE2', 1)
    INSERT [dbo].[MW_Warehouse] ([WarehouseID], [WarehouseName], [WarehouseCode], [Active]) VALUES (14, N'Warehouse 3', N'WARE3', 1)
    SET IDENTITY_INSERT [dbo].[MW_Warehouse] OFF
    /****** Object:  Table [dbo].[MW_WarehouseMerchantProduct]    Script Date: 04/30/2013 09:41:50 ******/
    SET IDENTITY_INSERT [dbo].[MW_WarehouseMerchantProduct] ON
    INSERT [dbo].[MW_WarehouseMerchantProduct] ([WarehouseMerchantProductID], [WarehouseID], [MerchantID], [ProductCode], [StockLevel], [Active], [PriorityOrder]) VALUES (93, 13, 24, N'TESTPRODUCT', 20, 1, 10)
    INSERT [dbo].[MW_WarehouseMerchantProduct] ([WarehouseMerchantProductID], [WarehouseID], [MerchantID], [ProductCode], [StockLevel], [Active], [PriorityOrder]) VALUES (96, 14, 24, N'TESTPRODUCT', 20, 1, 10)
    INSERT [dbo].[MW_WarehouseMerchantProduct] ([WarehouseMerchantProductID], [WarehouseID], [MerchantID], [ProductCode], [StockLevel], [Active], [PriorityOrder]) VALUES (97, 14, 27, N'TESTPRODUCT', 10, 1, 10)
    SET IDENTITY_INSERT [dbo].[MW_WarehouseMerchantProduct] OFF
    /****** Object:  Table [dbo].[MW_MerchantLink]    Script Date: 04/30/2013 09:41:50 ******/
    SET IDENTITY_INSERT [dbo].[MW_MerchantLink] ON
    INSERT [dbo].[MW_MerchantLink] ([MerchantLinkID], [MasterMerchantID], [LinkedMerchantID], [PreferenceOrder]) VALUES (22, 24, 27, 1)
    INSERT [dbo].[MW_MerchantLink] ([MerchantLinkID], [MasterMerchantID], [LinkedMerchantID], [PreferenceOrder]) VALUES (23, 24, 28, 2)
    SET IDENTITY_INSERT [dbo].[MW_MerchantLink] OFF
    

    在示例数据中,我返回的行应该是WarehouseMerchantProductID 93 93,96和97都有库存,但是

    93和96属于同一商家,应根据WarehouseMerchant表中的PreferenceOrder进行选择

    商家27链接到24,所以不应该出现(除非24缺货)

1 个答案:

答案 0 :(得分:0)

注意,以下查询是针对Oracle编写的,并假设LinkedMerchant只有1个MasterMerchant。您可以使用代码here。另请注意,为了测试其他一些案例,我提供了比您提供的更多的测试数据。

SELECT MERCHANTID, WAREHOUSEID, PRODUCTCODE
FROM (
  SELECT 0
  , WMP.MERCHANTID
  , WMP.WAREHOUSEID
  , WMP.PRODUCTCODE
  , RANK() OVER (PARTITION BY ML.MASTERMERCHANTID, WMP.PRODUCTCODE ORDER BY ML.PREFERENCEORDER ASC NULLS LAST) MERCH_RANK
  , RANK() OVER (PARTITION BY WMP.MERCHANTID, WMP.PRODUCTCODE ORDER BY WM.PREFERENCEORDER ASC NULLS LAST) WARE_RANK
  FROM MW_WAREHOUSEMERCHANTPRODUCT WMP
    LEFT OUTER JOIN MW_WAREHOUSEMERCHANT WM ON 0=0
                AND WMP.MERCHANTID  = WM.MERCHANTID
                AND WMP.WAREHOUSEID = WM.WAREHOUSEID
    LEFT OUTER JOIN MW_MERCHANTLINK ML ON 0=0
                AND WMP.MERCHANTID = ML.LINKEDMERCHANTID
    LEFT OUTER JOIN MW_WAREHOUSEMERCHANTPRODUCT MASTER ON 0=0
                AND ML.MASTERMERCHANTID = MASTER.MERCHANTID
                AND WMP.PRODUCTCODE     = MASTER.PRODUCTCODE
  WHERE 0=0
    AND WMP.STOCKLEVEL > 0
    AND NVL(MASTER.STOCKLEVEL, 0) <= 0
)
WHERE 0=0
  AND MERCH_RANK = 1
  AND WARE_RANK  = 1
;