【问题标题】:SQL select a date range for each parent/child family of itemsSQL 为每个父/子系列项目选择一个日期范围
【发布时间】:2016-06-28 17:20:29
【问题描述】:

我为所有具有范围键的父/子类型项目构建了一个层次结构(临时表)。我有一个表(LastOrdr),其中包含所有项目(无论父母/孩子)的最后订购日期。然后我有所有项目的主项目表。

我有一个查询,它选择满足特定 lastorderdate 条件的所有非父/子项目。这是一个简单的查询,它将主项目表与 LastOrdr 表连接起来,以从提供的用户参数中获取 max(lastorderdate)。

我的挑战是对父/子产品做同样的事情。对于父/子项目(一个父项,最多可以有 8 个子项,但在大多数情况下为 2/3)。选择是,对于一个家庭,max(lastorderdate) 必须应用于整个家庭。我的意思是,如果我的父母有 3 个孩子,我需要从 LastOrdr.lastorderdate 中找到这个家庭中所有 4 个(1 个父母和 3 个孩子)项目的最大值,然后将其与用户提供的参数进行比较。如果它符合家庭的标准,我想选择那个家庭,否则,放弃它。

我们将不胜感激提供一些指导。

谢谢。

Table1(主项):

itemID    ParentID    Descrip    ......
21         2           .....
22         2           .....
23         2           .....
24         2           .....
27         3           .....
29         3           .....
33         3           .....
41         3           .....
......................

表 2(LastOrdr):

ItemID    lastorderdate
2          2014-01-01
21         2014-07-21
21         2015-01-12
22         2013-01-01
23         2014-04-01
27         2013-01-23
...........................

【问题讨论】:

    标签: sql join parent-child


    【解决方案1】:

    以下查询返回您想要的。

    declare @master table (itemID int, ParentID int)
    insert @master values
    (21         ,2 ),
    ( 22         ,2), 
    ( 23         ,2 ),
    ( 24         ,2 ),
    ( 27         ,3 ),
    ( 29         ,3 ),
    ( 33         ,3 ),
    ( 41         ,3),
    (2, 2), --I added this data
    (3, 2)  --
    --,(44,21) --if you wish grandchild
    
    declare @LastOrdr table(ItemID int, lastorderdate date)
    insert @LastOrdr values
    (2          ,'2014-01-01'),
    (21         ,'2014-07-21'),
    (21         ,'2015-01-12'),
    (22         ,'2013-01-01'),
    (23         ,'2014-04-01'),
    (27         ,'2013-01-23')
    --,(44, '2015-04-15') --grandchild's order
    
    ;with master as (--create recursive (hierarchical) CTE
    --anchor query: items w/out parents
    select itemid, itemid ParentID --fix value
    from @master where ParentID = itemId --parent to itsellf
    union all
    --recursive query down the tree
    select m.itemid, m1.ParentID
    from @master m
    inner join master m1 on m.ParentID=m1.itemID
    )--end CTE
    select m.ParentID, max( lo.lastorderdate) lastorderdate
    from master m
    inner join @LastOrdr lo on m.itemID=lo.ItemID --join by childId
    where lo.lastorderdate< '2015-05-29' -- use ISO date
    group by m.ParentID --group by parent
    

    【讨论】:

    • 亚历克斯,感谢您的回复。在master中,对于父记录,我有parentID = 2以及itemID = 2。父母不为空。您会做出哪些更改以适应您的查询?
    • 我喜欢它只返回符合条件的家庭的父记录。如果数据正确,我可以使用 parentid 选择每个家庭中的所有孩子。另外,我需要提供一个 where 子句,所以我添加了“...from master m where lastorderdate
    • 这取决于您,前提是您在所有 joingroup by 之前添加 where。该查询还考虑了孙子。你觉得答案可以接受吗?
    • 这是问题的一部分或我的主要观点。能够选择符合日期标准的家庭。我提供了一个日期,并希望确保 max(lastorderdate) 小于提供的日期。
    • 删除最终select中的where并在goup by...之后添加having max(LastReceivingDate)&gt;...
    【解决方案2】:

    您没有发布任何表结构,所以我只会给出我的一般方法。 首先,我将通过创建一个附加列来标识分组来对父母和孩子进行分组。我会UNION 父母和孩子们,还有额外的专栏parentId

    itemId | parentId
    1      | 1
    2      | 1
    7      | 1
    9      | 1
    3      | 3
    6      | 3
    

    从这里,您可以GROUP BY parentId 获取MAX(lastorderdate)。如果您发布表结构,我可以更详细。

    试试下面的查询:

    SELECT *
    FROM (
        SELECT a.ParentID, MAX(orderdate) AS 'LatestOrder'
        FROM table1 a
        JOIN Table2 b ON b.ItemID = a.ItemID
        GROUP BY ParentID
    ) c
    JOIN table2 d ON d.OrderDate = c.LatestOrder
    JOIN table1 e ON e.ItemId = d.ItemId AND e.ParentId = c.ParentID 
    

    【讨论】:

    • 添加了一些表结构。正如我在原始帖子中提到的,我还构建了一个 P/C 层次结构。你可以看到我那里已经有一个 parentID 字段。你能在伪选择语句中显示你的方法吗?
    • 当 Item 是父项时,ParentId 是否为 NULL?
    • 否,对于项目表中的父行,itemid=2 parentID=2。
    • 我的解决方案适用于直接(一级)父子关系。如果您有多个级别的父子关系,请使用 Alex 发布的递归 CTE。
    • 我从提出的两个解决方案中得到了 2 个不同的结果集。我有一个层次的关系。让我试着验证一下数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    相关资源
    最近更新 更多