2016-11-08 74 views
-1

我有一个难题。情况是我们有一个表(OSCL)。此表有一个链接到更多表(ODLN - > DLN1)的子表(SCL4)。SQL - 查找顶级父级和底级子级值

这里的窍门是,OSCL有链接递归地回到自己的项目(以下简称“u_callParent”领域将有一个“呼叫标识”它,它对应于)

通常情况下,会出现0 -3级别的“呼叫父母”,需要链接回查询中。但是,一旦进入蓝色月亮,可能会有多达15个家长电话级别。

该查询的最终目标是数据设置如下:

DLN1.DocEntry | ODLN.DocNum | DLN1.ItemCode | DLN1.StockPrice | 
DLN1.Quantity | DLN1.LineNum | most parental call id | most child close date 

以下是我与:

OSCL 
-------------------------------------- 
CallID | u_callParent | CloseDate | 
--------|----------------------------- 
11638 | null   | 7/1/2016 | 
11688 | 11638  | 7/3/2016 | 
12548 | 11688  | 7/7/2016 | 
12705 | 12548  | 7/8/2016 | 
12845 | 12705  | 7/15/2016 | 
13321 | 12845  | 7/18/2016 | 
13643 | 13321  | 7/21/2016 | 
13661 | 13643  | 7/24/2016 | 
13872 | 13661  | 7/29/2016 | 
-------------------------------------- 

^
    | 
    v 

SCL4 
------------------------ 
SrcvCallID | DocAbs | 
------------|----------- 
11638  | 7541  | 
11688  | null  | 
12548  | null  | 
12705  | null  | 
12845  | 8993  | 
13321  | 9305  | 
13643  | 9335  | 
13661  | 9408  | 
13872  | 10519 | 
------------------------ 

       ^
      /
      /
      /
      /
     /
      v 
ODLN 
------------------------ 
DocEntry | DocNum | 
------------|----------- 
7541  | 9540  | 
8993  | 10992 | 
9305  | 11304 | 
9335  | 11334 | 
9408  | 11407 | 
10519  | 12518 | 
------------------------ 

^
    | 
    v 

DLN1 
---------------------------------------------------- 
DocEntry | ItemCode  | Quantity | LineNum | 
------------|--------------------------------------- 
7541  | 6LH06990000 | 1  | 0  | 
7541  | 6LE49877000 | 1  | 1  | 
8993  | 6LE09191000 | 1  | 0  | 
8993  | 6LE09788000 | 1  | 1  | 
8993  | 6LE09132000 | 1  | 2  | 
8993  | 6LE09155000 | 1  | 3  | 
8993  | C010814000  | 1  | 4  | 
8993  | 6LH72649000 | 1  | 5  | 
9305  | LaborDefault | 2.113 | 0  | 
9335  | LaborDefault | 1  | 0  | 
9408  | LaborDefault | 1.131 | 0  | 
10519  | LaborDefault | 3.213 | 0  | 
10519  | 6LA15184000 | 3  | 1  | 
10519  | 6LE09604000 | 1  | 2  | 
---------------------------------------------------- 

Goal Results 
------------ 
DocEntry | DocNum | ItemCode | Quantity | LineNum | CallID | CloseDate | 
------------------------------------------------------------------------- 
7541  | 9540 | 6LH... | 1  | 0  | 11638 | 7/29/2016 | 
7541  | 9540 | 6LE4... | 1  | 1  | 11638 | 7/29/2016 | 
8993  | 10992 | 6LE0... | 1  | 0  | 11638 | 7/29/2016 | 
8993  | 10992 | etc... | 1  | 1  | 11638 | 7/29/2016 | 
8993  | 10992 |   | 1  | 2  | 11638 | 7/29/2016 | 
8993  | 10992 |   | 1  | 3  | 11638 | 7/29/2016 | 
8993  | 10992 |   | 1  | 4  | 11638 | 7/29/2016 | 
8993  | 10992 |   | 1  | 5  | 11638 | 7/29/2016 | 
9305  | 11304 |   | 2.113 | 0  | 11638 | 7/29/2016 | 
9335  | 11334 |   | 1  | 0  | 11638 | 7/29/2016 | 
9408  | 11407 |   | 1.131 | 0  | 11638 | 7/29/2016 | 
10519 | 12518 |   | 3.213 | 0  | 11638 | 7/29/2016 | 
10519 | 12518 |   | 3  | 1  | 11638 | 7/29/2016 | 
10519 | 12518 |   | 1  | 2  | 11638 | 7/29/2016 | 
------------------------------------------------------------------------- 

的箭头表示工作我的数据的样本表格之间的链接。

我写了下面的查询,返回正确的结果;然而,1:57只跑了23行(限制发起呼叫11638)。问题是我需要在where语句中使用日期范围参数运行它,并且我们不希望每次重新运行此查询时等待2分钟以上。

select s1.* 
, max(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(child15.callid, child14.callid),child13.callid),child12.callid),child11.callid),child10.callid),child9.callid),child8.callid),child7.callid),child6.callid),child5.callid),child4.callid),child3.callid),child2.callid),child1.callid),oscl.callID)) MinCallID 

FROM (
select odln.docentry 
, odln.docnum 
, dln1.itemcode 
, dln1.Quantity 
, dln1.LineNum 
, min(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(isnull(parent15.callid, parent14.callid),parent13.callid),parent12.callid),parent11.callid),parent10.callid),parent9.callid),parent8.callid),parent7.callid),parent6.callid),parent5.callid),parent4.callid),parent3.callid),parent2.callid),parent1.callid),oscl.callID)) MinCallID 

from SCL4 
inner join odln on odln.DocEntry = scl4.DocAbs 
left join dln1 on dln1.DocEntry = odln.DocEntry 
left join oscl on oscl.callid = scl4.SrcvCallID 
left join oscl parent1 on oscl.U_callParent = parent1.callID 
left join oscl parent2 on parent1.U_callParent = parent2.callID 
left join oscl parent3 on parent2.U_callParent = parent3.callID 
left join oscl parent4 on parent3.U_callParent = parent4.callID 
left join oscl parent5 on parent4.U_callParent = parent5.callID 
left join oscl parent6 on parent5.U_callParent = parent6.callID 
left join oscl parent7 on parent6.U_callParent = parent7.callID 
left join oscl parent8 on parent7.U_callParent = parent8.callID 
left join oscl parent9 on parent8.U_callParent = parent9.callID 
left join oscl parent10 on parent9.U_callParent = parent10.callID 
left join oscl parent11 on parent10.U_callParent = parent11.callID 
left join oscl parent12 on parent11.U_callParent = parent12.callID 
left join oscl parent13 on parent12.U_callParent = parent13.callid 
left join oscl parent14 on parent13.U_callParent = parent14.callID 
left join oscl parent15 on parent14.U_callParent = parent15.callID 



group by odln.docentry 
, odln.docnum 
, dln1.itemcode 
, dln1.Quantity 
, dln1.LineNum 

) s1 
left join oscl on oscl.callid = s1.MinCallID 
left join oscl child1 on child1.U_callParent = oscl.callID 
left join oscl child2 on child2.U_callParent = child1.callID 
left join oscl child3 on child3.U_callParent = child2.callID 
left join oscl child4 on child4.U_callParent = child3.callID 
left join oscl child5 on child5.U_callParent = child4.callID 
left join oscl child6 on child6.U_callParent = child5.callID 
left join oscl child7 on child7.U_callParent = child6.callID 
left join oscl child8 on child8.U_callParent = child7.callID 
left join oscl child9 on child9.U_callParent = child8.callID 
left join oscl child10 on child10.U_callParent = child9.callID 
left join oscl child11 on child11.U_callParent = child10.callID 
left join oscl child12 on child12.U_callParent = child11.callID 
left join oscl child13 on child13.U_callParent = child12.callid 
left join oscl child14 on child14.U_callParent = child13.callID 
left join oscl child15 on child15.U_callParent = child14.callID 

--where MinCallID = 11638 

group by s1.docentry 
, s1.docnum 
, s1.itemcode 
, s1.stockprice 
, s1.Quantity 
, s1.LineNum 
, s1.MinCallID 

order by s1.mincallid, docentry, LineNum 

我知道,这是一个有点笨拙,而且一定是把它写一个更好的办法,但对我的生活,我不能弄明白。

我也不能添加任何修改数据库表(所以我不能添加一个字段说“始发呼叫”或任何东西)。

值得一提的是,这些表都基于SAP Business One,并且在OSCL上具有u_callParent的UDF。

编辑:

基于下面的评论,我已经更新了查询,看起来像这样:

with cte as (

       SELECT 
        OSCL.CallID 
        , OSCL.U_callParent 
        , PLevel = 0 
        , TopParent = CallID 
       FROM OSCL 
       WHERE U_callParent is null 

       UNION ALL 

       SELECT 
        OSCL.CallID 
        , OSCL.U_callParent 
        , PLevel = cte.Plevel + 1 
        , cte.TopParent 
       FROM OSCL 
       INNER JOIN cte on oscl.U_callParent = cte.callID 
) 

SELECT 
cte.* , scl4.DocAbs, scl4.Object 
FROM cte 
left join scl4 on scl4.SrcvCallID = cte.callID 
where TopParent = 11638 

的问题是,现在,我需要得到OSCL.CloseDate为“最幼稚“的信息,我不确定是否有这样做的好方法。有什么想法吗?


编辑2:

好吧,貌似我想通了:

with cte as (

       SELECT 
        OSCL.CallID 
        , OSCL.U_callParent 
        , PLevel = 0 
        , TopParent = CallID 
       FROM OSCL 
       WHERE U_callParent is null 

       UNION ALL 

       SELECT 
        OSCL.CallID 
        , OSCL.U_callParent 
        , PLevel = cte.Plevel + 1 
        , cte.TopParent 
       FROM OSCL 
       INNER JOIN cte on oscl.U_callParent = cte.callID 
) 

SELECT 
odln.docentry, odln.docnum, dln1.itemcode, dln1.quantity, dln1.linenum, cte.TopParent, child.closeDate 
FROM cte 
left join scl4 on scl4.SrcvCallID = cte.callID 
left join (SELECT max(callid) callID, topParent from cte group by topParent) s1 on s1.TopParent = cte.TopParent 
inner join oscl Child on Child.callID = s1.callID 
left join odln on odln.ObjType = scl4.Object and odln.DocEntry = scl4.DocAbs 
left join dln1 on dln1.DocEntry = odln.DocEntry 
where cte.TopParent = 11638 

如果有一个更好的方法比用我最后的SELECT语句子查询,请让我知道,但这似乎正在迅速运行。

+0

听起来像你正在寻找一个递归CTE http://blog.sqlauthority.com/2008/07/28/sql-server-simple-example-of-recursive-cte/我会提供更多的帮助如果我能......我多年来都写了几篇,但它仍然让我受到了伤害,并立即封锁了我生命中的那一部分。 – Kritner

+0

“...全部基于具有UDF的SAP Business One”。_你不能让我们挂在那里!_Yup,一个递归的CTE是要走的路。 – HABO

+0

谢谢你们!我会研究,看看我能否让自己的大脑不受伤害。 ;) – phroureo

回答

1
with cte as (

      SELECT 
       OSCL.CallID 
       , OSCL.U_callParent 
       , PLevel = 0 
       , TopParent = CallID 
      FROM OSCL 
      WHERE U_callParent is null 

      UNION ALL 

      SELECT 
       OSCL.CallID 
       , OSCL.U_callParent 
       , PLevel = cte.Plevel + 1 
       , cte.TopParent 
      FROM OSCL 
      INNER JOIN cte on oscl.U_callParent = cte.callID 
) 

SELECT 
odln.docentry, odln.docnum, dln1.itemcode, dln1.quantity, dln1.linenum, cte.TopParent, child.closeDate 
FROM cte 
left join scl4 on scl4.SrcvCallID = cte.callID 
left join (SELECT max(callid) callID, topParent from cte group by topParent) s1 on s1.TopParent = cte.TopParent 
inner join oscl Child on Child.callID = s1.callID 
left join odln on odln.ObjType = scl4.Object and odln.DocEntry = scl4.DocAbs 
left join dln1 on dln1.DocEntry = odln.DocEntry 
where cte.TopParent = 11638 

下面是我发现最终工作的解决方案。