【问题标题】:SQL: Count of rows since certain value first occurred: keep countingSQL:自某个值首次出现以来的行数:继续计数
【发布时间】:2018-10-25 19:55:20
【问题描述】:

这是一个类似的场景 SQL: Count of rows since certain value first occurred

在 SQL Server 中,我试图计算自过去 5 天内首次观察到与今天相同的天气(假设今天是 2018 年 8 月 6 日)以来的天数。每个城镇。

这是数据:

+---------+---------+--------+--------+--------+
| Date    | Toronto | Cairo  | Zagreb | Ankara |
+---------+---------+--------+--------+--------+
| 1.08.18 | Rain    | Sun    | Clouds | Sun    |
| 2.08.18 | Sun     | Sun    | Clouds | Sun    |
| 3.08.18 | Rain    | Sun    | Clouds | Rain   |
| 4.08.18 | Clouds  | Sun    | Clouds | Clouds |
| 5.08.18 | Rain    | Clouds | Rain   | Rain   |
| 6.08.18 | Rain    | Sun    | Sun    | Sun    |
+---------+---------+--------+--------+--------+

这需要表现良好,但到目前为止我想出的只是针对每个城镇的单个查询(并且将有几十个城镇,而不仅仅是四个)。这可行,但不会扩展。

这是多伦多的...

SELECT 
    DATEDIFF(DAY, MIN([Date]), GETDATE()) + 1 
FROM
    (SELECT TOP 5 * 
     FROM Weather 
     WHERE [Date] <= GETDATE()
     ORDER BY [Date] DESC) a
WHERE 
    Toronto = (SELECT TOP 1 Toronto 
               FROM Weather
               WHERE DataDate = GETDATE())

...正确返回 4,因为今天有雨,过去 5 天内第一次下雨是 8 月 3 日。

但我想要返回的是这样的表格:

+---------+-------+--------+--------+
| Toronto | Cairo | Zagreb | Ankara |
+---------+-------+--------+--------+
| 4       | 5     | 1      | 5      |
+---------+-------+--------+--------+

对@Used_By_Already 接受的答案稍作修改的是这段代码:

CREATE TABLE mytable(
   Date    date  NOT NULL
  ,Toronto VARCHAR(9) NOT NULL
  ,Cairo   VARCHAR(9) NOT NULL
  ,Zagreb  VARCHAR(9) NOT NULL
  ,Ankara  VARCHAR(9) NOT NULL
);

INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180801','Rain','Sun','Clouds','Sun');
INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180802','Sun','Sun','Clouds','Sun');
INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180803','Rain','Sun','Clouds','Rain');
INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180804','Clouds','Sun','Clouds','Clouds');
INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180805','Rain','Clouds','Rain','Rain');
INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180806','Rain','Sun','Sun','Sun');

with cte as (
        select
              date, city, weather
        FROM (
              SELECT * from mytable
             ) AS cp
        UNPIVOT (
                  Weather FOR City IN (Toronto, Cairo, Zagreb, Ankara)
            ) AS up
    )

select 
        date, city, weather, datediff(day,ca.prior,cte.date)+1 as daysPresent
from cte
cross apply (
    select min(prev.date) as prior
    from cte as prev 
    where prev.city = cte.city
    and prev.date between dateadd(day,-4,cte.date) and dateadd(day,0,cte.date)
    and prev.weather = cte.weather
    ) ca

order by city,date

输出:

但是,我现在正在尝试的是继续计算“daysPresent”,即使在过去的五天之后也是如此。这意味着输出样本中最后一个标记的行应该显示 6。如果它们之间的间隔少于 5 天,逻辑是将前一个数字增加它们之间的天数。如果过去 5 天没有相同的天气,请返回 1。

我尝试了 LEAD 和 LAG,但无法让它发挥作用。向其中添加另一层甚至是正确的方法还是查询需要看起来完全不同?

我很困惑。

【问题讨论】:

  • 改为使用一个城市列,用于存储城市 ID。
  • 您能说得更具体些吗?上面的查询返回一个带有城市列的表。我需要更改的是按照上述逻辑的 dayPresent 计数器,谢谢。
  • 你的桌子设计有点奇怪。我会有一个包含 cityid 和 cityname 列的城市表。还有一个包含日期、cityid 和天气列的天气表。 (简化。)
  • 您应该解释您要解决的问题,而不必让别人在两个不同的问题之间翻来覆去弄清楚您的问题可能是什么。
  • 表格设计不在我的控制范围内。无论如何它都是抽象的,真正的表格看起来不同。我知道这很糟糕,但我必须处理它。

标签: sql sql-server common-table-expression lag lead


【解决方案1】:

您的数据结构存在重大问题。这些值应该在 rows 中,而不是在 columns 中。所以,开始吧:

select d.dte, v.*from data d cross apply
     (values ('Toronto', Toronto), ('Cairo', Cairo), . . .
     ) v(city, val)
where d.date >= dateadd(day, -5, getdate());

从那里,我们可以使用窗口函数first_value()(或last_value())来获取最近的读数。其余的只是按城市聚合:

with d as (
      select d.dte, v.*,
             first_value(v.val) over (partition by v.city order by d.dte desc) as last_val
      from data d cross apply
           (values ('Toronto', Toronto), ('Cairo', Cairo), . . .
           ) v(city, val)
      where d.date >= dateadd(day, -5, getdate())
     )
select city, datediff(day, min(dte), getdate()) + 1
from d
where val = last_val
group by city;

这会以行而不是列的形式为您提供所需的信息。如果你真的想要,你可以重新旋转。但我建议您将数据与城市数据放在不同的行中。

【讨论】:

  • 我知道结构很糟糕。它在现实中并不完全如此,但显然是出于性能原因在报告数据库中创建的。现在,新的要求使设计不当的结构变得痛苦。不幸的是,我无法控制它。您的查询完美无缺,谢谢@gordon-linoff!我从整件事中学到了很多。
  • 我意识到它不能长时间工作......我已经改写了我的问题@gordon-linoff stackoverflow.com/questions/53037973/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-04
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多