当前位置: 首页 > 面试题库 >

SQL:从首次出现某些值以来的行数

梁昊天
2023-03-14
问题内容

在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      |
+---------+-------+--------+--------+

这怎么可能?


问题答案:

您确实不想尝试对数据透视表执行此操作,尽管您声明数据不是以这种方式存储的,但您没有向我们展示如何以列为中心到达城市的透视图。耻辱。

因此,我已经在一个公用表表达式中“取消透视”了该样本,然后使用apply operator来对前5天相同天气的先前发生次数进行计数。看来您知道如何旋转,我将其留给您来旋转最终结果。

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, ca.prior
from cte
cross apply (
    select count(*) as prior
    from cte as prev 
    where prev.city = cte.city
    and prev.date between dateadd(day,-6,cte.date) and dateadd(day,-1,cte.date)
    and prev.weather = cte.weather
    ) ca

使用此样本数据:

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');

上面的查询产生了以下结果:

+----+---------------------+---------+---------+-------+
|    |        date         |  city   | weather | prior |
+----+---------------------+---------+---------+-------+
|  1 | 01.08.2018 00:00:00 | Ankara  | Sun     |     0 |
|  2 | 02.08.2018 00:00:00 | Ankara  | Sun     |     1 |
|  3 | 03.08.2018 00:00:00 | Ankara  | Rain    |     0 |
|  4 | 04.08.2018 00:00:00 | Ankara  | Clouds  |     0 |
|  5 | 05.08.2018 00:00:00 | Ankara  | Rain    |     1 |
|  6 | 06.08.2018 00:00:00 | Ankara  | Sun     |     2 |
|  7 | 01.08.2018 00:00:00 | Cairo   | Sun     |     0 |
|  8 | 02.08.2018 00:00:00 | Cairo   | Sun     |     1 |
|  9 | 03.08.2018 00:00:00 | Cairo   | Sun     |     2 |
| 10 | 04.08.2018 00:00:00 | Cairo   | Sun     |     3 |
| 11 | 05.08.2018 00:00:00 | Cairo   | Clouds  |     0 |
| 12 | 06.08.2018 00:00:00 | Cairo   | Sun     |     4 |
| 13 | 01.08.2018 00:00:00 | Toronto | Rain    |     0 |
| 14 | 02.08.2018 00:00:00 | Toronto | Sun     |     0 |
| 15 | 03.08.2018 00:00:00 | Toronto | Rain    |     1 |
| 16 | 04.08.2018 00:00:00 | Toronto | Clouds  |     0 |
| 17 | 05.08.2018 00:00:00 | Toronto | Rain    |     2 |
| 18 | 06.08.2018 00:00:00 | Toronto | Rain    |     3 |
| 19 | 01.08.2018 00:00:00 | Zagreb  | Clouds  |     0 |
| 20 | 02.08.2018 00:00:00 | Zagreb  | Clouds  |     1 |
| 21 | 03.08.2018 00:00:00 | Zagreb  | Clouds  |     2 |
| 22 | 04.08.2018 00:00:00 | Zagreb  | Clouds  |     3 |
| 23 | 05.08.2018 00:00:00 | Zagreb  | Rain    |     0 |
| 24 | 06.08.2018 00:00:00 | Zagreb  | Sun     |     0 |
+----+---------------------+---------+---------+-------+

自首次发生以来的天数(过去5天内)

select 
        date, city, weather, datediff(day,ca.prior,cte.date) as prior
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,-6,cte.date) and dateadd(day,-1,cte.date)
    and prev.weather = cte.weather
    ) ca


 类似资料:
  • 问题内容: 假设我有一张选举数据表,称为选举,每个选举每个选民都有一行,如下所示: 我想知道在选举1和选举2中都投票的选民人数;我不在乎别人 该数字应为2(选民A和选民E)。 这样的事情会做: 更新:这是我在这里的第一个问题,我被那些热心而又快速的人们所震撼。我修改了上面的查询,以解决最后缺少别名并添加终止分号的问题。 谢谢你! 问题答案: 是的。你所拥有的应该工作。(您将需要在派生表上添加一个别

  • 问题内容: 我在numpy中有一个1D数组,我想在值超过numpy数组中的值的位置找到索引的位置。 例如 查找超出值的位置。 问题答案: 这有点快(看起来更好) 因为将在第一个位置停止(“如果多次出现最大值,则返回对应于第一个出现的索引。”)并且不会保存其他列表。

  • 问题内容: 假设我有一张桌子: 我插入一些行: 因此,我最终得到了一个类似于以下内容的表: 我该如何选择每组相同数字的第一个日期,所以我得到了以下结果: 我整天大部分时间都在忙着子查询之类的事情,由于某种原因,我似乎无法破解它。我敢肯定某个地方有一个简单的方法! 我可能想从结果中排除0,但目前并不重要。 问题答案: 修订日期:2011年1月15日 我敢肯定某个地方有一个简单的方法! 就在这里。但是

  • 问题内容: 我正在尝试创建一个SQL查询,该查询将拉取自Windows函数内的最后一个最大值起的最后5行以来的行数。在下面的示例中,它将为第8行返回2。最大值为12,即从第8行起的2行。 对于第6行,它将返回5,因为7的最大值位于5行之外。 我尝试了以下方法: 这使我达到最大值,但是我无法有效地确定它有多少行。我能够使用SELECT中的多个变量来接近,但这似乎没有效率或可伸缩性。 问题答案: 您可

  • 问题内容: 假设您有下表(这里关注的列是): 如何只提取每个的第一次出现?结果表将是: 问题答案: mysql对此有一个“作弊”: 这就是你所需要的,因为在MySQL中它可以让你 没有 聚集不分组,按列(其他数据库将抛出一个语法错误),在这种情况下,输出仅对每个第一次出现组由值(S)。不过,请注意,这将无法保证的 方式 中,“第一”发生确定(这将是行只是如何读) 如果您要先出现某个 特定的东西,

  • 本文向大家介绍Python中首次出现真数,包括了Python中首次出现真数的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们需要在给定的数字列表中找到第一个出现的非零数字。 与枚举和下一个 我们起诉枚举以获取所有元素的列表,然后应用下一个函数以获取第一个非零元素。 示例 输出结果 运行上面的代码给我们以下结果- 与下一个和过滤器 将next和filter条件以及lambda表达式应用于条件不