我遇到了一个我自己无法解决的情况,希望获得支持如何解决它: 我目前正在 SQL Server 18 上构建一个数据仓库。在临时数据库中,我有一个 SoLine 表,它组合了多个 Oracle 表中的数据。这些表中有 ONT.OE_Order_Price_Attribs,其中包含要连接到基表 ONT.OE_Order_Lines_All 的 Header_Id 和 Line_Id:
SELECT
OL.*,
OPA.*
FROM ONT.OE_Order_Lines_All OL
LEFT JOIN ONT.OE_Order_Price_Attribs OPA
ON OL.Header_Id = OPA.Header_Id
AND OL.Line_Id = OPA.Line_Id
OPA 有时每个 Header_Id、Line_Id 和 Last_Update_Date 包含多个记录(因此这些记录包含所有相同的值):
标题_Id | 线路_Id | 最后更新日期 | 定价_上下文 | 订单_价格_属性_Id | Att1 | Att2 | Att3 | Att4 | Att5 |
---|---|---|---|---|---|---|---|---|---|
123 | 456 | 2023-12-13 10:00:00 | 01 | 789 | A | B | C | D | E |
123 | 456 | 2023-12-13 10:00:00 | 01 | 790 | A | B | C | D | F |
除了 Order_Price_Attrib_Id 列之外,其余列也相同。但 att* 列可能相同或不同。
我想要实现的是我只有 1 条记录作为结果。如果 Header_Id、Line_Id 和 Last_Update_Date 列相同,则应显示具有最新 Order_price_Attrib_Id 的记录。因此,在上面的示例中,Id 为 790,无论 att* 是否相同或不同。但我确实想看看 att* 列
因此,对于订单行表中的每个 Header_Id 和 Line_Id 组合,都需要根据 SoLine 表中每条记录的 Order_Price_Attrib_Id 找到 attrib 表的最新 Header_Id 和 Line_id。 因此(至少我认为)需要一个循环来找到每个组合。
我尝试在 Order_Price_Attrib_Id 上使用 MAX 函数,但遗憾的是没有成功。我还尝试使用带有 count(*) 等的子查询。但不幸的是到目前为止还没有结果。
我很难编写这些更高级/更困难的查询,因为我不是编写查询的真正专家。我可以编写基础知识,但目前这些类型的查询有点遥不可及。
因此,我们非常感谢任何帮助,因此已经提前感谢您。
约里
我似乎没有以任何方式让 SoLine 表中的每条记录只有 1 条记录作为结果
我们可以使用
ROW_NUMBER()
为由 PARTITION BY
子句指定的定义组内的每一行分配唯一的序号,然后我们选择每组的最新行,使用 ORDER BY
子句按降序对数据进行排序:
SELECT *
FROM (
SELECT
OL.*,
OPA.*,
ROW_NUMBER() OVER (PARTITION BY OL.Header_Id, OL.Line_Id, OL.Last_Update_Date ORDER BY Order_Price_Attrib_Id DESC) AS rn
FROM OE_Order_Lines_All OL
LEFT JOIN OE_Order_Price_Attribs OPA
ON OL.Header_Id = OPA.Header_Id
AND OL.Line_Id = OPA.Line_Id
) AS S
WHERE rn = 1;
这是一个古老的问题,T-SQL 中的一个解决方案是
outer apply
功能:
select
OL.*,
OPA.*
from ONT.OE_Order_Lines_All OL
outer apply (select top 1 *
from ONT.OE_Order_Price_Attribs OPA
where OL.Header_Id = OPA.Header_Id
and OL.Line_Id = OPA.Line_Id
order by Order_price_Attrib_Id desc) OPA
如您所见,这实际上为
OL
中的每一行运行一个子查询,按 OPA.Order_price_Attrib_Id
排序并仅给出第一个结果,因此最终结果集保持相同的大小。
您可以使用两个
left joins
执行类似的操作,但查询最终可能会更加复杂(不过可能性能更好):
select
OL.*,
OPA.*
from ONT.OE_Order_Lines_All OL
left join ONT.OE_Order_Price_Attribs OPA
on OL.Header_Id = OPA.Header_Id
and OL.Line_Id = OPA.Line_Id
left join ONT.OE_Order_Price_Attribs OPAX
on OL.Header_Id = OPAX.Header_Id
and OL.Line_Id = OPAX.Line_Id
and OPAX.Order_price_Attrib_Id > OPA.Order_price_Attrib_Id
where OPAX.Order_price_Attrib_Id is null
在这里,您还再次连接来自
ONT.OE_Order_Price_Attribs
的所有行,但前提是 Order_price_Attrib_Id
大于之前连接的 Order_price_Attrib_Id
。然后丢弃所有不为空的结果,即只保留不存在更大的 Order_price_Attrib_Id
的结果。正如你所看到的,我将其中一张连接表命名为 OPAX
来表示它只能被扔掉。您当然可能更喜欢其他东西,也许OPA_greater
或其他东西。