【问题标题】:Getting records with month by month, year by year and day by day from SQL Server从 SQL Server 获取逐月、逐年、逐日的记录
【发布时间】:2014-06-18 00:16:44
【问题描述】:

我正在寻找一种快速简便的 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
...
..

我在这张表上有超过 200 万条记录。

第一:

我想获得 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。

压倒选民,这个问题成了“热门问题”。现在请解释为什么投反对票?

【问题讨论】:

  • 这是一道超级简单的SQL题。你有没有尝试过?
  • 尝试了一些。例如,我不知道如何从 2014 年的最大值中获取。我在 2014 年有 200 万条记录。我想从 2014 年获得最大值行。其他年份也是如此......
  • 您熟悉year()month()day() 函数吗?

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


【解决方案1】:

以下假设您想要的不仅仅是每个日期/月份的最大值,还想知道该行的 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() 函数都会为catID, date 中的每个PARTITION 创建一个数字序列(1,2,3,4,etc),按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

【讨论】:

  • 非常感谢您的回答 :) 当我执行“For daily”时得到这个:i.imgur.com/vv5AHAF.png;我想得到所有的日子。我该怎么做?谢谢
  • @ErçinDedeoğlu - 该屏幕截图暗示 MeterID=3 您只有一个日期的数据。
  • @ErçinDedeoğlu - 两个观察结果。 1. 您的字段名称是MeterReadDate 而不是Date,因此查询需要在PARTITION BY 中包含MeterReadDate2. 这些不是日期,而是日期时间。如果您想要它per date,那么您需要使用PARTITION BY MeterID, DATEADD(DAY, DATEDIFF(DAY, 0, MeterReadDate), 0) 将该字段向下舍入到一天的开始。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
  • 2013-08-09
  • 2023-03-27
相关资源
最近更新 更多