我正在尝试根据成员根据购买日期支付的最近价格,对2个或更多成员进行购买价格比较。
我有四个表:成员,项目,UOM和事实
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)
我的用户界面允许选择两个或更多成员,以便比较每个人的价格。我的结果集必须包含至少有两个选定成员购买该项目并排除所有其他成员的项目。
我通过以下方式在临时表中设置我的成员列表:
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表时使用临时表进行过滤。
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。)根据购买日期仅显示每位会员\ item \ 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
答案 0 :(得分: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;
答案 1 :(得分:0)
我能够自己解决这个问题,但会发表我自己的答案;也许它可以帮助其他有类似任务的人。
我能够通过引入第二个临时表来确定每个项目和成员的最新购买价格来完成这三项任务。然后将#mostrecentpurchase临时表加入基表,可以进行有效的成员价格比较。
要将结果集限制为只有两个或多个所选成员记录价格的项目,我使用OVER子句并按项目和计量单位进行分区,以获得每个项目/ uom的成员数。然后,我在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;