0

我正在尝试根据会员根据购买日期支付的最新价格,对 2 个或更多会员进行购买价格比较。

我有四个表:Member、Items、UOM 和 Fact

Member (membername varchar(50), memberkey int)

Items  (itemname varchar(50), itemkey int)

UOM    (uomname varchar(50), uomkey int)

Fact   (memberkey int, itemkey int, uomkey int, purchaseamount decimal(18,2), quantity int, purchasedate date)

我的 UI 允许选择两个或多个成员以允许比较每个单位的价格。我的结果集必须包含至少有两个选定成员购买了该项目并排除所有其他项目的项目。

我通过以下方式在临时表中设置了我的成员列表:

    declare @MemberKeys as varchar(max)
    set @MemberKeys = '702,1382,1389,1390,1391,1392,1393,1394,1395,1396,1397,1401,1402,1404,1405,1406,1516,1844';
    create table #mk (memberName varchar(253), memberkey smallint)

    insert into #mk (memberName, memberkey)
    Select Rownbr + '.)  '  +  membername, memberkey from (
    SELECT
        cast(ROW_NUMBER() OVER(ORDER BY [MemberFacilityName] ASC) as varchar (10)) AS RowNbr
        ,k.value as memberkey
        ,m.memberName

    FROM 
        Member m
        INNER JOIN dbo.String_To_SmallInt_Table(@MemberKeys, ',') AS k
        ON m.Memberkey = k.value            
        ) X

然后我在查询fact、uom和item表时使用temp表进行过滤。

    select m.membername
    ,i.itemname
    ,u.uomname
    ,purchaseamount 
    ,quantity
    ,purchaseamount/quantity as price  
    from Fact f
    join #mk m
    on m.memberkey = f.memberkey
    join Item i
    on i.itemkey = f.itemkey
    join UOM u
    on u.uomkey= f.uomkey

现在我需要执行以下操作,但需要一些指导来完成它。

1.) 过滤掉至少两个选定成员未使用的项目。

2.) 根据购买日期,仅显示每个会员\商品\uom 的最新购买价格。

3.) 排序结果集以显示成员然后项目以便于比较(类似于下面的简化列表)。

Member   Item   Price
 mbr1       A   1.11
 mbr2       A   1.12
 mbr3       A   1.52
 mbr4       A   2.01
 mbr1       B   3.01
 mbr2       B   3.03
 mbr3       B   3.12
 mbr4       B   3.41
 mbr1       C   6.01
 mbr2       C   6.63
 mbr3       C   6.92
 mbr4       C   6.99
4

2 回答 2

1

这是我如何实现的......告诉我我的逻辑是否合理:

/****Create Sample Data*****/

-->Member table
IF exists (SELECT 1 from dbo.sysobjects WHERE name = 'Member')
DROP TABLE Member
GO

CREATE TABLE Member (membername VARCHAR(50), memberkey INT)
GO 
INSERT INTO Member VALUES
('mbr1',702),
('mbr2',1382),
('mbr3',1389),
('mbr4',1390),
('mbr5',1391),
('mbr6',1392),
('mbr7',1393),
('mbr8',1394),
('mbr9',1395),
('mbr10',1396),
('mbr11',1397),
('mbr12',1401),
('mbr13',1402),
('mbr14',1404),
('mbr15',1405),
('mbr16',1406),
('mbr17',1516),
('mbr18',1111)-->Should NOT show up in query
GO

-->Items table
IF exists (SELECT 1 from dbo.sysobjects WHERE name = 'Items')
DROP TABLE Items
GO

CREATE TABLE Items  (itemname VARCHAR(50), itemkey INT)
GO
INSERT INTO Items VALUES
('A',1),
('B',2),
('C',3),
('D',4)

GO

-->UOM table   
IF exists (SELECT 1 from dbo.sysobjects WHERE name = 'UOM')
DROP TABLE UOM
GO
CREATE TABLE UOM    (uomname VARCHAR(50), uomkey INT)
GO

INSERT INTO UOM  VALUES ('QTY', 1)
GO

-->Fact table
IF exists (SELECT 1 from dbo.sysobjects WHERE name = 'Fact')
DROP TABLE Fact
GO
CREATE TABLE Fact   (memberkey INT, itemkey INT, uomkey INT, purchaseamount      decimal(18,2), quantity INT, purchasedate date)
GO

INSERT INTO Fact VALUES 
(702,  1, 1, 1.11, 2, '1/3/2012'),-->Should show up in query
(1382, 1, 1, 1.12, 3, '1/4/2013'),-->Should NOT show up in query
(1382, 1, 1, 1.14, 2, '7/5/2013'),-->Should show up in query
(1404, 1, 1, 1.21, 2, '1/7/2012'),-->Should show up in query
(1401, 2, 1, 3.01, 1, '4/2/2013'),-->Should NOT show up in query
(1111, 3, 1, 6.92, 1, '12/12/2012'),-->Should NOT show up in query
(702,  3, 1, 5.01, 2, '4/1/2011'),-->Should show up in query
(1401, 3, 1, 4.01, 1, '6/5/2012'),-->Should show up in query
(1397, 4, 1, 5.45, 1, '7/4/2013'),-->Should NOT show up in query
(1397, 4, 1, 5.22, 3, '3/15/2011')-->Should NOT show up in query
GO


/*****Code to get results*****/
BEGIN  

-->Members to Filter On
DECLARE @MemberKeys AS VARCHAR(max)
SET @MemberKeys = '702,1382,1389,1390,1391,1392,1393,1394,1395,1396,1397,1401,1402,1404,1405,1406,1516,1844';


-->Parse out comma delimited VALUES into a table variable
DECLARE @Member TABLE 
(
memberkey INT
)
DECLARE @spot SMALLINT, @str VARCHAR(max), @sql VARCHAR(max)  

WHILE @MemberKeys <> ''  
BEGIN  
    SET @spot = CHARINDEX(',', @MemberKeys)  
    IF @spot>0  
        BEGIN  
            SET @str = LEFT(@MemberKeys, @spot-1) 
            SET @MemberKeys = RIGHT(@MemberKeys, LEN(@MemberKeys)-@spot)  
        END  
    ELSE  
        BEGIN  
            SET @str = @MemberKeys 
            SET @MemberKeys = ''  
        END  
    INSERT INTO @Member VALUES(CONVERT(VARCHAR(100),@str))   
END  

END;


-->Display Results
WITH staged(memberkey, membername, itemname ,itemkey, uomname, uomkey, purchaseamount, quantity, price, purchasedate, noitems )  
AS
(
SELECT 
 m.memberkey
,m.membername
,i.itemname
,i.itemkey
,u.uomname
,u.uomkey
,f.purchaseamount 
,f.quantity
,f.purchaseamount/f.quantity as price  
,f.purchasedate
,COUNT(m.memberkey) OVER(PARTITION BY i.itemkey )-COUNT(m.memberkey) OVER(PARTITION BY  convert(VARCHAR,m.memberkey)+convert(VARCHAR,i.itemkey) ) as noitems
FROM 
Fact f
    JOIN Member m ON m.memberkey = f.memberkey
    JOIN Items i ON i.itemkey = f.itemkey
    JOIN UOM u ON u.uomkey= f.uomkey
 WHERE 
 EXISTS(SELECT 1 FROM @Member m2 WHERE m.memberkey=m2.memberkey)
 )
 SELECT
      memberkey, 
      membername, 
      itemname ,
          itemkey,
      uomname, 
          uomkey,
      sum(purchaseamount) as purchaseamount , 
      sum(quantity) as quantity , 
      sum(price) as price, 
      max(purchasedate) as purchasedate
 FROM
      staged st
 WHERE
          noitems>0
          and exists(
    select  memberkey, 
            itemkey ,
            uomkey,
            max(purchasedate) as maxdate 
           from staged st2 
                            where st.memberkey=st2.memberkey 
                            and st.itemkey=st2.itemkey 
                            and st.uomkey=st2.uomkey

            group by  
            memberkey, 
            itemkey ,
            uomkey
            having st.purchasedate=max(st2.purchasedate)
            )
 GROUP BY 
          memberkey 
     ,membername  
     ,itemname  
     ,uomname
         , itemkey 
     , uomkey 
 ORDER BY 
         itemname 
         ,memberkey;
于 2013-08-22T16:12:52.467 回答
0

我能够自己解决这个问题,但会发布我自己的答案;也许它可以帮助其他人完成类似的任务。

通过引入第二个临时表来确定每件商品和会员的最新购买价格,我能够完成这三项任务。然后将#mostrecentpurchase 临时表加入到基表中,可以进行有效的会员价格比较。

为了将结果集限制为仅包含两个或多个选定成员已记录价格的项目,我使用了 OVER 子句并按项目和计量单位进行分区,以获取每个项目/单位的成员计数。然后我在 where 子句中使用这个计数来过滤掉计数小于 1 的行。

最后,排序是通过简单的 order by 子句完成的。完成的 tsql 脚本如下。

    declare @MemberKeys as varchar(max)

    set @MemberKeys = '702,1382,1389,1390,1391,1392,1393,1394,1395,1396,1397,1401,1402,1404,1405,1406,1516,1844';

    create table #mk (memberName varchar(253), memberkey smallint)


    insert into #mk (memberName, memberkey)
    Select Rownbr + '.)  '  +  membername, memberkey from (
    SELECT
        cast(ROW_NUMBER() OVER(ORDER BY [MemberFacilityName] ASC) as varchar (10)) AS RowNbr
        ,k.value as memberkey
        ,m.memberName

    FROM 
        Member m
        INNER JOIN dbo.String_To_SmallInt_Table(@MemberKeys, ',') AS k
        ON m.Memberkey = k.value            
        ) X

    create table #mostrecentpurchase(purchasedate date, itemkey int, uomkey int, memberkey int)

    Insert into #mostrecentpurchase(purchasedate, itemkey, uomkey, memberkey)
    select max(f.PurchaseDate) purchasedate
    , f.itemKey
    , f.uomkey
    , f.memberkey
    from  Fact f
    join #mk m
    on m.memberkey = f.memberkey
    group by f.itemkey
    , f.uomkey
    , f.memberkey


    select x.* FROM (
    select m.memberName
    , i.itemname
    , i.itemkey
    , f.purchasedate
    , sum(f.purchaseamount) as purchaseamount
    , sum(f.quantity) as quantity
    , u.uomname
    , sum(f.purchaseamount)/sum(f.quantity) as price 
    , count(m.memberName) OVER(PARTITION BY i.vendorItem_PK,u.UnitOfmeasure) AS mbrCount
    from 
    fact f
    join #mk m
    on m.memberkey = f.memberkey
    join #mostrecentpurchase mrp
    on mrp.purchasedate = f.PurchaseDate
    and mrp.memberkey = f.memberkey
    and mrp.uomkey = f.uomkey
    and mrp.vendoritemkey = f.itemkey
    join item i
    on i.itemkey = f.itemkey
    join uom u
    on u.uomkey = f.uomkey
    group by m.membername,i.itemname,i.itemkey,f.purchasedate,u.uomname
    ) X
    where mbrCount >= @MemberCompCount
    order by X.itemname, X.memberName


    drop table #mk;
    drop table #mostrecentpurchase;
于 2013-08-22T14:56:10.147 回答