2010-02-17 78 views
1

我试图将Linq查询转换为SQL。我的Linq查询如下所示:你可以在SQL中编写自定义聚合函数吗?你可以查询分组的内容吗?

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 

在这个例子中,我内心非法查询被用作聚合功能相同的作用。

回答

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 

,但它在大多数情况下,相当不错。而且好的一点是,你可以修改这个来做每组前2名,前3名等,并且你可以完全控制关系。

(附注:我希望你不实际name列“查询”)

+0

对不起,查询是特定领域的东西泄漏到我的结构域的问题。我编辑了它。我现在将调查这个row_number的东西:) – dmnd 2010-02-17 02:24:59

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,这将返回多个记录。但它应该是你正在寻找的东西。

相关问题