我正在尝试将Linq查询转换为SQL。我的Linq查询如下所示:
from s in Somethings
where s.CreatedTime >= new DateTime(2010, 01, 01)
where s.CreatedTime < new DateTime(2010, 02, 01)
group s by s.Data into grouping
select grouping.OrderByDescending(s => s.CreatedTime)
.ThenByDescending( s => s.UpdatedTime)
.First();
用语言来说,这应该是从某个月开始的所有事情。然后按特定键对它们进行分组。对于每个键,我想要最近创建的元素。如果同时创建了具有相同键的两个元素,我想通过最近更新的方式来断开关系。
到目前为止,我已经将其用于SQL
了SELECT s1.*
FROM Somethings s1
JOIN (
SELECT s.Date AS Data, MAX(CreatedTime) AS CreatedTime
FROM Somethings s
WHERE s.CreatedTime >= '20100101'
AND s.CreatedTime < '20100201'
GROUP BY s.Data
) s2 ON s1.Data = s2.Data
AND s1.CreatedTime = s2.CreatedTime
这有效,但我无法控制关系是如何被打破的。
我真正想要的是一种在Linq中任意排序每个分组的方法。我想定义自己的聚合函数,它接受一组行,并返回一行。这可能在SQL中,还是Linq更具表现力? SQL的聚合函数MAX,MIN,COUNT等似乎不像Linq中的等价函数那样是第一类函数。当然,这可能只是我对SQL的了解不足。
这是一个用于进一步说明我想在SQL中做什么的组成示例:
SELECT (SELECT *
FROM grouping
ORDER BY CreatedTime DESC, UpdatedTime DESC
LIMIT 1)
FROM Somethings s
WHERE s.CreatedTime >= '20100101'
AND s.CreatedTime < '20100201'
GROUP BY s.Data AS grouping
在此示例中,我的非法内部查询提供与聚合函数相同的角色。
答案 0 :(得分:2)
这不是一个真正的聚合,它只是一个分组最大值。 ROW_NUMBER
是编写这些查询的最简单方法:
;WITH CTE AS
(
SELECT
Query, CreatedTime, UpdatedTime, <other_columns>,
ROW_NUMBER() OVER
(
PARTITION BY Query
ORDER BY CreatedTime DESC, UpdatedTime DESC
) AS RowNum
FROM Somethings
WHERE CreatedTime >= '20100101'
AND CreatedTime < '20100201'
)
SELECT *
FROM CTE
WHERE RowNum = 1
它不一定是效率最高的,但在大多数情况下它都相当不错。而且好处是你可以修改它来做每组前3名,前3名等,你可以完全控制关系。
(P.S。我希望你实际上并没有将列命名为“查询”)
答案 1 :(得分:0)
在sql中使用Group By展平组中的记录。这允许您在组上执行聚合函数,返回有关组的信息(最小值,最大值,计数等),但不能访问每个组中的各个记录。
也许这不能回答你的问题......
再添加一个级别,再次分组,最大更新时间......这应该可以解决您的问题。
SELECT sFinal.* FROM Somethings sFinal
JOIN
(
SELECT s1.Query, MAX(UpdatedTime) AS UpdatedTime
FROM Somethings s1
JOIN (
SELECT s.Query AS Query, MAX(CreatedTime) AS CreatedTime
FROM Somethings s
WHERE s.CreatedTime >= '20100101'
AND s.CreatedTime < '20100201'
GROUP BY s.Query
) s2
ON s1.Query = s2.Query
AND s1.CreatedTime = s2.CreatedTime
GROUP BY s1.Query
) s3
ON sFinal.Query = s3.Query AND sFinal.UpdatedTime = s3.UpdatedTime
现在,如果它们具有匹配的CreatedTime和UpdatedTime,则将返回多个记录。但它应该是你想要的。