从SQL Server逐月,逐年和逐日获取记录

时间:2014-05-01 13:51:01

标签: c# sql sql-server tsql stored-procedures

我正在寻找一种快速简便的SQL查询来逐年,逐月和逐日获取记录。

我的数据库示例:

ID - DATE        - CatID - VALUE
1  - 2013-08-06  -  32   -  243
2  - 2013-08-16  -  2    -  45
3  - 2013-08-21  -  2    -  1
4  - 2013-08-05  -  32   -  450
5  - 2013-08-05  -  32   -  449
6  - 2013-08-05  -  32   -  11
7  - 2013-08-01  -  2    -  221
8  - 2013-08-02  -  32   -  0
9  - 2013-08-02  -  32   -  0
10 - 2013-08-02  -  32   -  987
...
..

我在这张桌子上有超过2百万条记录。

首先

我想获得当天的CatID = 32和单/更高记录。

结果:

1  - 2013-08-06  -  32   -  243
4  - 2013-08-05  -  32   -  450
10 - 2013-08-02  -  32   -  987

第二

我想和 MONTH 一样。

如何使用SQL SERVER执行此操作。目前是Sql Server 2012。

也使用C#5,如果你想使用,EF 6。

1 个答案:

答案 0 :(得分:2)

以下假设您不仅需要每个日期/月的最大值,还想知道该行的id等等。


每日......

WITH
  sorted AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY CatID,
                                    Date
                           ORDER BY Value DESC)   AS ordinal_cat_date
  FROM
    yourTable
)
SELECT
  *
FROM
  sorted
WHERE
  ordinal_cat_date = 1
  AND catID = 32

每月......

WITH
  sorted AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY CatID,
                                    DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0)
                           ORDER BY Value DESC)   AS ordinal_cat_month
  FROM
    yourTable
)
SELECT
  *
FROM
  sorted
WHERE
  ordinal_cat_month = 1
  AND catID = 32

在这两种情况下,ROW_NUMBER()函数按(1,2,3,4,etc)的降序为PARTITION的每个catID, date创建一系列数字value。任何行的值为1的行都是该分区中值最大的行。

公式DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0)只会将Date向下舍入到该月的第一天,从而创建整个月的分区。


如果这些行共享相同的最高值,则每天/每月会带来多行的其他一些选项...

SELECT  -- Daily Version
  *
FROM
  yourTable
WHERE
  NOT EXISTS (SELECT *
                FROM yourTable   AS lookup
               WHERE lookup.CatID = yourTable.CatID
                 AND lookup.Value > yourTable.Value
                 AND lookup.Date  = yourTable.Date
             )
  AND CatID = 32


SELECT  -- Monthly Version
  *
FROM
  yourTable
WHERE
  NOT EXISTS (SELECT *
                FROM yourTable   AS lookup
               WHERE lookup.CatID  = yourTable.CatID
                 AND lookup.Value >  yourTable.Value
                 AND lookup.Date  >= DATEADD(MONTH,   DATEDIFF(MONTH, 0, yourTable.Date), 0)
                 AND lookup.Date  <  DATEADD(MONTH, 1+DATEDIFF(MONTH, 0, yourTable.Date), 0)
             )
  AND CatID = 32


或者可能......

SELECT  -- Daily Version
  *
FROM
  yourTable
INNER JOIN
(
  SELECT
    Date,
    CatID,
    MAX(Value)   AS max_value
  FROM
    yourTable
  GROUP BY
    CatID,
    Date
)
  AS lookup
    ON  yourTable.Date  = lookup.Date
    AND yourTable.CatID = lookup.CatID
    AND yourTable.Value = lookup.max_value
WHERE
  yourTable.CatID = 32


SELECT  -- Monthly Version
  *
FROM
  yourTable
INNER JOIN
(
  SELECT
    CatID,
    DATEADD(MONTH, DATEDIFF(MONTH, 0, yourTable.Date), 0)   AS month_start,
    MAX(Value)   AS max_value
  FROM
    yourTable
  GROUP BY
    CatID,
    DATEADD(MONTH, DATEDIFF(MONTH, 0, yourTable.Date), 0)
)
  AS lookup
    ON  yourTable.Date  >= lookup.month_start
    AND yourTable.Date  <  DATEADD(MONTH, 1, lookup.month_start)
    AND yourTable.CatID  = lookup.CatID
    AND yourTable.Value  = lookup.max_value
WHERE
  yourTable.CatID = 32