在 SQL Server 查询中复制 MS Access “First”函数
Posted
技术标签:
【中文标题】在 SQL Server 查询中复制 MS Access “First”函数【英文标题】:Replicating the MS Access "First" function in SQL Server Query 【发布时间】:2012-10-16 14:29:19 【问题描述】:我对 SQL Server 很陌生,所以我现在向您道歉。
我有一张表,我想 GroupBy field1
并返回 field2
记录,该记录在 counted
字段中具有最高的关联计数。我通常会在 MS ACCESS 中使用 2 个查询来执行此操作,第一个查询以降序返回数据,第二个查询使用 First() 函数选择第一条记录,如下所示:-
查询 1
SELECT t.field1, t.field2, Count(t.counted) AS count1
FROM Table1 AS t
WHERE (((t.counted)=2))
GROUP BY t.field1, t.field2
ORDER BY t.field1, Count(t.counted) DESC;
查询 2(基于上面的查询 1)
SELECT q.field1, First(q.field2) AS firstoffield2
FROM q
GROUP BY q.field1;
SOURCE DATA and query results I am looking for
我很难在 SQL Server 2008 查询中完成与上述相同的结果。有人可以帮忙吗? (请提供我需要使用的准确 SQL)。
这是数据的子集和结果示例:-
表1
field1 ¦ field2 ¦ counted
10 ¦ 20 ¦ 2
10 ¦ 30 ¦ 2
10 ¦ 20 ¦ 2
20 ¦ 30 ¦ 0
20 ¦ 40 ¦ 0
20 ¦ 50 ¦ 1
20 ¦ 50 ¦ 2
20 ¦ 60 ¦ 1
Query1 结果(按字段 1 分组,计数“计数”字段记录为“2”)
field1 ¦ field2 ¦ count1
10 ¦ 20 ¦ 2
10 ¦ 30 ¦ 1
20 ¦ 50 ¦ 1
查询 2 个结果(我想从 SQL 得到的输出)
field1 ¦ firstoffield2
10 ¦ 20
20 ¦ 50
希望对大家有所帮助,谢谢。
【问题讨论】:
T-SQL 中没有与 FIRST 函数直接等效的函数。根据您的描述,使用 MAX 语句似乎可以解决问题,但如果我们有一些示例数据并且您可以突出显示您希望该过程返回的内容,这将很有帮助。通过这种方式,我们可以查看您想要的结果,并尝试想出一些可以解决问题的方法。 好的,谢谢蒂姆。我会发布数据。 Link to Source Data @FranzSigmar 指向源数据的链接失败,您可以编辑您的帖子并将数据放在这里吗? 有上传文件的方法吗? 【参考方案1】:WITH
q AS
(
Put your query one here
)
,
sequenced AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY field1 ORDER BY count1 DESC) AS sequence_id,
*
FROM
q
)
SELECT
*
FROM
sequenced
WHERE
sequence_id = 1
要将其更改为 LAST(),请更改 ROW_NUMBER() 函数中的订单方向。
【讨论】:
将 ROW_NUMBER() 更改为 DENSE_RANK() 以在出现平局时返回所有行。 (即使出现平局,此答案目前也只会选择一个。) 太棒了,我不能感谢你足够的 Dems,如果你在这里,我会拥抱你或请我的妻子 - 随你喜欢 :-) @FranzSigmar - 不客气 :) 随意为有帮助的答案投票,并为您个人接受最好的答案。 (我不反对你或你的妻子,但我更喜欢啤酒谢谢...) 太棒了,我对 Dems 感激不尽,我刚刚检查了所有的输出,结果很准确。我不得不缩小一个并删除了 ORDER BY 命令:- ORDER BY t.field1, Count(t.counted) DESC;我很高兴在出现平局的情况下选择任何一排,这不会经常发生,在任何情况下都无关紧要。我有最后一个问题,如何将此 WITH 语句放入可以在存储过程中使用的选择查询中?再次感谢 Dems,非常感谢您的帮助。 查找公用表表达式 (CTE)。您将它们放在主要语句之前,就好像您正在创建单独的子查询或内联视图一样。然后,您只需像使用任何其他视图/表格一样使用它们。祝你好运。【参考方案2】:这不是我写过的最优雅的查询,但是这样的查询怎么样:
SELECT qSource.Field1, qSource.Field2
FROM (SELECT Field1, Field2, COUNT(Counted) AS Count1
FROM dbo.Table1
WHERE Counted = 2
GROUP BY Field1, Field2)qSource
INNER JOIN (SELECT q.Field1,MAX(q.Count1) AS HighestCount
FROM (SELECT Field1, Field2, COUNT(Counted) AS Count1
FROM dbo.Table1
WHERE Counted = 2
GROUP BY Field1, Field2) q
GROUP BY q.Field1) qHighest
ON qSource.Field1 = qHighest.Field1
AND qSource.Count1 = qHighest.HighestCount
ORDER BY qSource.Field1
【讨论】:
使用 CTE 让它更整洁一些。此外,如果第一个存在平局,则此方法会返回所有平局行,而 FIRST() 则不会。这可能是一个优势,也可能不是,这取决于 OP 需要什么。但 OP 只要求复制 FIRST()。 @Dems 感谢您的提示。我喜欢你的方法! 嗨,蒂姆,非常感谢这对我也有用,但 Dems 只是打败了你。对于其他任何人,Tim 的查询也会返回 tie,而 Dems 查询不会,所以我想你可以简单地剪切和粘贴你需要的那个。【参考方案3】:我一直在寻找同样的东西,不喜欢复杂的解决方案,所以我一直在寻找并找到了这个:
https://www.sqlservercentral.com/forums/topic/t-sql-equivalent-to-ms-access-first-function
使用“前 1”
选择 Top 1 SomeColumn 来自 SomeTable 订购方式
这真的很好,因为您添加了复杂 ORDER BY 的功能,如果有多个第一,您就可以准确地获得所需的功能
【讨论】:
以上是关于在 SQL Server 查询中复制 MS Access “First”函数的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MySQL 中打破类似于 MS SQL Server 的列名?