您如何检索每个分组中的前两条记录

Posted

技术标签:

【中文标题】您如何检索每个分组中的前两条记录【英文标题】:How do you retrieve the top two records within each grouping 【发布时间】:2013-10-23 19:44:15 【问题描述】:

在我的表中,我的数据如下所示:

CODE    DATE    PRICE
100     1/1/13  $500
100     2/1/13  $521
100     3/3/13  $530
100     5/9/13  $542
222     3/3/13  $20
350     1/1/13  $200
350     3/1/13  $225

是否可以创建查询以提取DATE 的两条最新记录?并且仅当特定代码有 2 个以上日期时。所以结果是:

CODE    DATE    PRICE
100     5/9/13  $542
100     3/3/13  $530
350     3/1/13  $225
350     1/1/13  $200

如果您可以将两个价格/日期放在同一行,则可以获得奖励积分,如下所示:

CODE    OLD_DATE    OLD_PRICE    NEW_DATE    NEW_PRICE
100     3/3/13      $530         5/9/13      $542
350     1/1/13      $200         3/1/13      $225

谢谢!!!

【问题讨论】:

来吧,杰夫。有了 50 多个问题,您应该知道接下来会发生什么……您尝试过什么,尝试过什么? How to select top 10 in Access query?的可能重复 @GordThompson 我尝试了以DATE 作为标题和PRICE 作为值的交叉表查询,但它为表中的每个日期创建了一个列。 【参考方案1】:

我设法用 5 个子查询和 1 个汇总查询解决了这个问题。

首先我们有一个子查询,它为我们提供每个代码的 MAX 日期。 接下来,我们执行相同的子查询,只是我们排除了之前的结果。 我们假设您的数据已经汇总,并且您不会有相同代码的重复日期。

接下来,我们为最近和第二个最晚日期输入适当的代码/价格。如果代码在 2nd Max 查询中不存在 - 那么我们根本不包含它。

在联合查询中,我们将两者的结果结合起来。在汇总查询中,我们对联合中生成的空值进行排序和删除。

结果:

CODE    MaxOfOLDDATE    MaxOfOLDPRICE   MaxOfNEWDATE    MaxOfNEWPRICE
100     2013-03-03      $530.00     2013-05-09      542
350     2013-01-01      $200.00     2013-03-01      225

在名为“表”的表中使用您的数据,创建以下查询:

SUB_2ndMaxDatesPerCode:

SELECT Table.CODE, Max(Table.Date) AS MaxOfDATE1
FROM SUB_MaxDatesPerCode RIGHT JOIN [Table] ON (SUB_MaxDatesPerCode.MaxOfDATE = Table.DATE) AND (SUB_MaxDatesPerCode.CODE = Table.CODE)
GROUP BY Table.CODE, SUB_MaxDatesPerCode.CODE
HAVING (((SUB_MaxDatesPerCode.CODE) Is Null));

SUB_MaxDatesPerCode:

SELECT Table.CODE, Max(Table.Date) AS MaxOfDATE
FROM [Table]
GROUP BY Table.CODE;

SUB_2ndMaxData:

SELECT Table.CODE, Table.Date, Table.PRICE
FROM [Table] INNER JOIN SUB_2ndMaxDatesPerCode ON (Table.DATE = SUB_2ndMaxDatesPerCode.MaxOfDATE1) AND (Table.CODE = SUB_2ndMaxDatesPerCode.Table.CODE);

SUB_MaxData:

SELECT Table.CODE, Table.Date, Table.PRICE
FROM ([Table] INNER JOIN SUB_MaxDatesPerCode ON (Table.DATE =  SUB_MaxDatesPerCode.MaxOfDATE) AND (Table.CODE = SUB_MaxDatesPerCode.CODE)) INNER JOIN SUB_2ndMaxDatesPerCode ON Table.CODE = SUB_2ndMaxDatesPerCode.Table.CODE;

SUB_Data:

SELECT CODE, DATE AS OLDDATE, PRICE AS OLDPRICE, NULL AS NEWDATE, NULL AS NEWPRICE FROM SUB_2ndMaxData;
UNION ALL SELECT CODE, NULL AS OLDDATE, NULL AS OLDPRICE, DATE AS NEWDATE, PRICE AS NEWPRICE FROM SUB_MaxData;

数据(汇总):

SELECT SUB_Data.CODE, Max(SUB_Data.OLDDATE) AS MaxOfOLDDATE, Max(SUB_Data.OLDPRICE) AS MaxOfOLDPRICE, Max(SUB_Data.NEWDATE) AS MaxOfNEWDATE, Max(SUB_Data.NEWPRICE) AS MaxOfNEWPRICE
FROM SUB_Data
GROUP BY SUB_Data.CODE
ORDER BY SUB_Data.CODE;

你去 - 谢谢你的挑战。

【讨论】:

谢谢!这就是我一直在寻找的......获取最近日期的过程,然后是第二个最近的日期,然后是每个日期的价格,然后将它们放在一起。我无法在脑海中解决这个问题。【参考方案2】:

访问最近的数据

要访问最近的数据,请使用TOP 2。比如你把表中的数据倒过来,然后选择top 2。就像你从ZYX开始ABC,然后选择TOP 2,它会给你提供ZY。

SELECT TOP 2 * FROM table_name ORDER BY column_time DESC;

这样,您可以反转表格,然后从顶部选择最近的两个。

加入表格

要连接两列并从那里创建结果,您可以使用 JOIN(INNER JOIN;我更喜欢这个),例如:

SELECT TOP 2 * FROM table_name INNER JOIN table_name.column_name ON 
table_name.column_name2

这样,您将连接两个表,其中一个列中的值与两个表中另一列中的值匹配。

您可以为此使用for 循环来选择它们的值,或者您可以在foreach 循环中使用它来取出它们的值。

我的建议

我最好的方法是,首先选择使用日期排序的数据。

然后在 foreach() 循环中,您将在其中写入数据,选择该时间的剩余数据。并将其写入该循环中。

代码(column_name)不会打扰您

当您使用ORDER By Time Desc 引用查询时,您将不再使用代码,例如WHERE Code = value。您将获得最新代码的代码。如果您确实需要code 列,可以使用 if else 阻止将其过滤掉。

参考:

http://technet.microsoft.com/en-us/library/ms190014(v=sql.105).aspx(内连接)

http://www.w3schools.com/sql/sql_func_first.asp(顶部;检查 Sql Server 查询)

【讨论】:

谢谢 .. 我不知道 TOP 2 是一个东西。我过去做过TOP 10,但没想过要尝试其他数字。我会试试看的!! 当然,您可以尝试任何数字来选择最高值:) 我认为比这更复杂。这只会为您提供前 2 条记录,而不是按代码显示的前 2 条记录。 我从来没有提到他想要 CODE 的前 2 条记录的 OP。 :) 他只想要 TOP 2 列 :) 事实上,他想忽略CODE,这样他就不必担心不同代码的匹配日期。不是这样吗?

以上是关于您如何检索每个分组中的前两条记录的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询 - 返回连接表的前两条记录的连接

如何为mysql中的每条记录检索表中的两条记录

在 Access 子报表中使用 top 子句

SQL查询每月每天的前两条数据....

是否可以从分区中的每个聚类键Y中选择X记录?

SQL 检索最新记录,按唯一外键分组