gpt4 book ai didi

sql - 对所选记录进行排序、分组和重新排序的问题

转载 作者:行者123 更新时间:2023-12-05 00:55:52 25 4
gpt4 key购买 nike

底线:

我有一个 Sub 应该对一组记录重新排序,但它的核心查询并不是在罕见的特定情况下按预期对记录进行分组和排序。

背景:

我正在开发一个系统升级,供教育人员将类(class)信息发布到我们的内部网。在现有和升级后的系统中,Classes_Dates表包含与日期相关的所有信息,包括“系列”编号。

系列号曾经(现在仍然)用于对日期进行分组和排序,主要是为了加快前端的页面生成速度。类(class)在给定的系列中可以有一个或多个(无限制)日期。

在现有系统中,序列号是手动管理的。通常,这不是问题。类按它们出现的顺序依次输入。有时,在按时间顺序排列的中间添加一个类(class),工作人员将手动重新排列系列编号以正确地对日期进行分组/排序。它有效,但如果新员工不经常使用该系统,他们很难学习和留住现有员工。

在升级中,我写了一个 sub 来自动处理组的重新排序。我试图保留这个概念,但把它埋起来,这样工作人员就不需要知道它仍然存在。

这是 sub 本身,每次添加新的类(class)日期时都会调用:

Sub ReorderGroups(intClassID)
strSQL = "SELECT DateID, Series, ClassStart "
strSQL = strSQL & "FROM Classes_Dates "
strSQL = strSQL & "WHERE ClassID = " & intClassID & " "
strSQL = strSQL & "GROUP BY Series, ClassStart, DateID "
strSQL = strSQL & "ORDER BY ClassStart;"

Dim objSQLDB : Set objSQLDB = CreateObject("ADODB.Command")
objSQLDB.ActiveConnection = strSQLConn

Dim objDates : Set objDates = Server.CreateObject("ADODB.Recordset")
objDates.Open strSQL, strSQLConn, adOpenDynamic, adLockReadOnly, adCmdText
If Not objDates.BOF Then objDates.MoveFirst
If Not objDates.EOF Then
Dim intNewSeries : intNewSeries = 1
Dim intCurrentOld : intCurrentOld = cLng(objDates("Series"))

Do Until objDates.EOF
If intCurrentOld <> cLng(objDates("Series")) Then
intNewSeries = cLng(intNewSeries) + 1
intCurrentOld = cLng(objDates("Series"))
End If

objSQLDB.CommandText = "UPDATE Classes_Dates SET Series = " & intNewSeries & " WHERE DateID = " & objDates("DateID")
objSQLDB.Execute ,,adCmdText

objDates.MoveNext
Loop
End If
objDates.Close
Set objDates = Nothing
Set objSQLDB = Nothing
End Sub

我确信有一种更有效的方式来写这个,但我首先关心的是让它工作 - 然后我可能会将它发布到 CodeReview.SE 以获得一些优化帮助。

只要没有两个日期重叠的系列,子就可以很好地工作。下列:
SELECT DateID, Series, ClassStart
FROM Classes_Dates
WHERE ClassID = 11
GROUP BY Series, ClassStart, DateID
ORDER BY ClassStart;

正在收集这个结果集:

DateID 系列类开始
------ ------ --------------
49 1 20100907080000
51 1 20100913080000
50 1 20100916080000
56 2 20100921080000
57 2 20100927080000
58 2 20100929080000
'--剪断--'
670 12 20110614080000
671 12 20110615080000
672 13 20110705080000
676 15 20110707080000
674 14 20110709090000
673 13 20110714080000
675 14 20110716080000

而不是我所期望的:

DateID 系列类开始
------ ------ --------------
49 1 20100907080000
51 1 20100913080000
50 1 20100916080000
56 2 20100921080000
57 2 20100927080000
58 2 20100929080000
'--剪断--'
670 12 20110614080000
671 12 20110615080000
672 13 20110705080000
673 13 20110714080000
676 15 20110707080000
674 14 20110709090000
675 14 20110716080000

我需要在 SQL 中修复什么?或者有没有更好的方法来获得相同的最终结果?

后者可能会更好,因为我现在再次查看它时可以看到,随着时间的推移,这不会很好地扩展......

最佳答案

我想你想要:

SELECT DateID, Series, ClassStart
FROM Classes_Dates
WHERE ClassID = 11
GROUP BY Series, ClassStart, DateID
ORDER BY MIN(ClassStart) OVER(PARTITION BY Series)
, ClassStart

注意,如果 (Series, ClassStart, DateID)是此表中的唯一键,那么您甚至不需要 GROUP BY:
SELECT DateID, Series, ClassStart
FROM Classes_Dates
WHERE ClassID = 11
ORDER BY MIN(ClassStart) OVER(PARTITION BY Series)
, ClassStart

并且只是为了捕捉两个系列具有相同 MIN(ClassStart) 的(可能很少见的)情况,您应该使用这个,这样来自这两个系列的数据不会在结果中混淆:
SELECT DateID, Series, ClassStart
FROM Classes_Dates
WHERE ClassID = 11
ORDER BY MIN(ClassStart) OVER(PARTITION BY Series)
, Series
, ClassStart

查询的工作原理:

您的问题描述的是您希望数据按组显示(相同 Series )。但是您还希望根据 MIN(ClassStart) 对这些组进行排序。每个组的。

MIN(ClassStart)我们必须使用 GROUP BY Series但我们不能这样做,因为这样(同一组的)多行会合并为一行。

这是什么 MIN(ClassStart) OVER(PARTITION BY Series)达到。它计算 minimum of ClassStart 好像 我们用过 GROUP BY Series .

关于sql - 对所选记录进行排序、分组和重新排序的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6508846/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com