我有下表和数据。
create table items
(
itemid int
,userid varchar(10)
,itemtype varchar(10)
,value varchar(10)
);
insert into items values (101,'usr1','CST','');
insert into items values (101,'usr1','GST','');
insert into items values (100,'usr1','Data','a25');
insert into items values (100,'usr1','GST','');
insert into items values (99,'usr3','Data','a50');
insert into items values (98,'usr3','CST','');
insert into items values (98,'usr3','GST','');
insert into items values (97,'usr3','CST','');
insert into items values (96,'usr3','Data','a25');
insert into items values (96,'usr3','GST','');
insert into items values (95,'usr3','Data','a50');
insert into items values (95,'usr3','GST','');
这是一个发票行表,其中包含项目中每行的详细信息。某些发票行没有“数据”类型的行。对于这些记录,我们需要遍历该表并通过匹配userid找到其中包含“Data”值的 next lower itemid ,获取该值并将其作为输出。
这是预期的输出 -
itemid,userid,itemtype,value
101,usr1,CST,a25
101,usr1,GST,a25
98,usr3,CST,a25
98,usr3,GST,a25
97,usr3,CST,a25
可以看出,itemid 101从itemid 100中获取值。同样,itemid的98和97从itemid 96获得了valeus。
我编写了以下查询以获取所有不包含数据的发票 -
;with cte_groupdata
as
(
select itemid
,userid
,case
when itemtype = 'Data' then 1
else 0
end as rn
from items
group by itemid
,userid
,case
when itemtype = 'Data' then 1
else 0
end
)
,cte_validdata
as
(
select itemid
,userid
,count(*) as total
from cte_groupdata
group by itemid
,userid
)
select vld.itemid
,vld.userid
,it.itemtype
from cte_validdata vld
join items it
on vld.userid = it.userid
and vld.itemid = it.itemid
where vld.total = 1
and it.itemtype <> 'Data';
我收到了我需要处理的所需发票。我知道我需要编写一个共同相关的子查询。我只是无法理解如何设置条件。这是一个prod数据,我们没有创建UDF或过程的权限。
答案 0 :(得分:2)
使用cross join lateral
就足够了:
create table items ( itemid int ,userid varchar(10) ,itemtype varchar(10) ,value varchar(10) );
insert into items values (101,'usr1','CST',''), (101,'usr1','GST',''), (100,'usr1','Data','a25'), (100,'usr1','GST',''), (99,'usr3','Data','a50'), (98,'usr3','CST',''), (98,'usr3','GST',''), (97,'usr3','CST',''), (96,'usr3','Data','a25'), (96,'usr3','GST',''), (95,'usr3','Data','a50'), (95,'usr3','GST','');
select i.itemid, i.userid, i.itemtype, cjl.datavalue from items i cross join lateral ( select value as datavalue from items i2 where i.userid = i2.userid and i.itemid > i2.itemid and i2.itemtype = 'Data' and i2.value <> '' order by i2.itemid desc limit 1 ) cjl where i.itemtype <> 'Data'
itemid | userid | itemtype | datavalue -----: | :----- | :------- | :-------- 101 | usr1 | CST | a25 101 | usr1 | GST | a25 98 | usr3 | CST | a25 98 | usr3 | GST | a25 97 | usr3 | CST | a25 96 | usr3 | GST | a50
dbfiddle here
答案 1 :(得分:1)
您可以尝试NOT EXISTS
子句将行过滤到没有数据的行,然后将其与包含相关子查询的联接组合以获取缺少的数据:
select i.itemid, i.userid, i.itemtype,
iprev.value
from items i
join items iprev
on iprev.userid = i.userid
and iprev.itemtype = 'Data'
and iprev.value <> ''
and iprev.itemid = (select max(i2.itemid)
from items i2
where i2.itemid < i.itemid
and i2.userid = iprev.userid
and i2.itemtype = iprev.itemtype
and i2.value <> '')
where i.value = ''
and not exists (select null
from items i2
where i2.itemid = i.itemid
and i2.userid = i.userid
and i2.value <> '')