我正在尝试学习sql,它使我发疯。我似乎无法掌握实现所需输出的正确语法。我正在观看udemy上的视频并阅读有关试图自学的基本sql书籍,但似乎它们都不足以帮助我弥合我似乎无法克服的差距。
我对SELECT,FROM,WHEN命令的基础知识有很好的了解。我似乎在了解使用聚合函数的知识,但我绝不是专家。
我有两个表,“订单”和“ OrderDet”。 “订单”包含CustomerName和OrderNo,而OrderDet包含其他所有内容,例如PartNo,DateFinished,OrderNo等。
我有多个客户可以订购相同零件号的情况。我想显示所有客户下的所有最后订单。
例如
SELECT Orders.CustDesc, OrderDet.OrderNo, OrderDet.PartNo, OrderDet.DateFinished
FROM Orders
JOIN OrderDet ON Orders.OrderNo = OrderDet.OrderNo
ORDER BY OrderDet.PartNo, OrderDet.DateFinished
此查询返回:
Customer OrderNo PartNo Date Finished
--------------------------------------------------------
Cust 1 5032 12345678-1 NULL
Cust 2 10032 12345678-1 2019-06-05 14:54:25.853
Cust 2 1048 12345678-1 2019-07-08 00:00:00.000
Cust 1 5028 12345678-1 2019-09-30 11:45:45.960
Cust 1 5029 12345678-1 2019-09-30 12:49:35.713
Cust 1 5030 12345678-1 2019-09-30 13:04:57.333
Cust 1 5031 12345678-1 2019-10-10 13:58:22.653
我仍在学习何时以及如何使用聚合函数,但是似乎无法完全掌握该概念。我尝试在“日期”列上使用MAX,并在“客户和零件号”上使用GROUP,但是除非删除订单号,否则输出永远不会折叠到我想要的位置。
例如,我使用过:
SELECT Orders.CustDesc, OrderDet.PartNo, MAX(OrderDet.DateFinished)
FROM Orders
JOIN OrderDet ON Orders.OrderNo = OrderDet.OrderNo
GROUP BY Orders.CustDesc, OrderDet.PartNo
ORDER BY OrderDet.PartNo
从SELECT中删除OrderDet.OrderNo,并从Order By中删除OrderDet.DateFinished。这将返回我想要的行输出,但是缺少我想要的所有列。
Customer PartNo Date Finished
--------------------------------------------
Cust 2 12345678-1 2019-07-08 00:00:00.000
Cust 1 12345678-1 2019-10-10 13:58:22.653
我尝试将OrderNo重新添加到混合中时,得到的输出与第一个相同。我想我理解为什么会这样,因为所有的OrderNo都是唯一的并且无法分组,但是我无法掌握如何克服这个问题。
我了解这是基本的SQL命令,但似乎无法理解如何获取所需的输出。在此示例中,我只想根据PartNo的最后日期看到两行唯一的客户,但要显示整行的内容。不只是三栏。
同样,我正在尝试学习这些内容,并且我只能阅读和重新阅读相同的基本内容,以学习这么长时间。我阅读的所有内容似乎都缺少那一刻“ AH HA”所需的信息。
也许有人可以帮助弥合这种差距?
我将您的问题解释为想要给定客户的每个订购的零件的最新订单。
为此,我建议使用窗口功能:
select CustDesc, OrderNo, od.DateFinished
from (select o.custdesc, od.orderno, od.partno, od.datefinished,
row_number() over (partition by o.custdesc, od.partno order by od.datefinished desc) as seqnum
from Orders o join
orderdet od
on o.OrderNo = od.OrderNo
) od
where seqnum = 1;
order by od.PartNo, od.DateFinished
解决这个问题的关键是:不要聚合,而是过滤。
从列出每个OrderDet
的所有Order
的现有查询开始,您可以添加一个联接条件,该联接条件使用correlated子查询以每个OrderDet
的最新Order
进行过滤:] >
SELECT o.CustDesc, d.OrderNo, d.PartNo, d.DateFinished From Order o JOIN OrderDet d ON o.OrderNo = d.OrderNo AND d.DateFinished = ( SELECT MAX(d1.DateFinished) FROM Order o1 JOIN OrderDet d1 ON o1.OrderNo = d1.OrderNo WHERE o1.CustDesc= o.CustDesc ) Order By d.PartNo, d.DateFinished
另一个典型的解决方案是使用窗口函数
RANK()
,如果您的RDBMS支持的话:
SELECT o.CustDesc, d.OrderNo, d.PartNo, d.DateFinished FROM ( SELECT o.*, d.*, RANK() OVER(PARTITION BY d.CustDesc ORDER BY d.DateFinished DESC) rn From Order o JOIN OrderDet d ON o.OrderNo = d.OrderNo ) t WHERE rn = 1
内部查询查询按
CustDesc
降序对具有相同DateFinished
的记录组中的每个记录进行排名。然后,外部查询将在每个组的顶部记录上进行过滤。
旁注:有意义的表别名使查询更短,更容易理解。我修改了您现有的查询以使用它们。