简体   繁体   English

如何将不带过滤器的子查询连接到带过滤器的查询?

[英]How can I connect a subquery without filters to a query with filters?

I have a query similar to the simplified one below.我有一个类似于下面简化的查询。

SELECT
  Users.ID,
  Registrations.Timestamp
FROM
  Users,
  Registrations
WHERE
  Users.ID = Registrations.UserID AND
  Registrations.Date >= '2020-02-27'
ORDER BY
  Users.ID,
  Registrations.Timestamp;

I want to calculate a third column named Type with the values entry and departure like the following desired result:我想计算名为Type的第三列,其值为entrydeparture ,如下所示:

ID  | Timestamp           | Type
----+---------------------|----------
1   | 2020-02-27 05:43:24 | entry
1   | 2020-02-27 13:48:47 | departure
1   | 2020-02-28 05:44:38 | entry
1   | 2020-02-28 13:50:11 | departure
2   | 2020-02-27 13:44:41 | entry
2   | 2020-02-27 21:47:54 | departure
2   | 2020-02-28 13:40:16 | entry
2   | 2020-02-28 21:52:57 | departure
3   | 2020-02-27 05:46:20 | departure
3   | 2020-02-28 21:44:05 | entry
3   | 2020-02-28 05:47:18 | departure

The way it calculates it is by counting the amount of registrations up to that one (without the Date filter).它的计算方式是计算注册数量到那个数量(没有Date过滤器)。 If the resulting count number is odd then consider it an entry else if it's even a departure .如果结果计数为奇数,则将其视为entry否则如果它是偶数departure

In the example the user number 3 starts as departure because even though it is the first registration (odd number), without the Date filter it's an even number.在示例中,用户编号 3 以departure开始,因为即使它是第一次注册(奇数),如果没有Date过滤器,它也是偶数。

I have tried using a subquery but can't figure out how to count only up to the Timestamp , not all of them.我试过使用子查询,但不知道如何只计算到Timestamp ,而不是全部。

SELECT
  Users.ID,
  Registrations.Timestamp,
  CASE WHEN
    (
      SELECT
        COUNT(Registrations.Timestamp)
      FROM
        Registrations
      WHERE
        Registrations.UserID = OuterUsers.ID AND
        Registrations.Timestamp <= OuterRegistrations.Timestamp
    ) % 2 = 0 THEN
    'departure'
  ELSE
    'entry'
  END AS Type
FROM
  Users,
  Registrations
WHERE
  Users.ID = Registrations.Timestamp.UserID AND
  Registrations.Date >= '2020-02-27'
ORDER BY
  Users.ID,
  Registrations.Timestamp;

This sort of problem is likely not unique but I can't figure out even one solution to it from searching through some similar questions.这类问题可能不是唯一的,但我无法通过搜索一些类似的问题找出一种解决方案。

Use row_number() first and then filter.首先使用row_number()然后过滤。 Also use to learn proper,explicit, standard , readable JOIN syntax:也用于学习正确的、明确的、标准的、可读的JOIN语法:

Select u.*, r.*,
       (case when seqnum % 2 = 1  then 'entry' else 'departure' end) as type
FROM users u JOIN
     (SELECT r.*,
             ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date) as seqnum
      FROM Registrations r
     ) r
     ON u.ID = r.Timestamp.UserID
WHERE r.Date >= '2020-02-27'
ORDER BY u.ID, r.Timestamp;

Why don't you add a rank/row number ordered by timestamp and use these values to determine departure and entry instead为什么不添加按时间戳排序的排名/行号并使用这些值来确定出发和进入

Select *, case when row_num % 2 = 0  then 'departure' else 'entry' end as type
FROM
(SELECT
    Users.ID,
     row_number() over (partition by ID order by timestamp) as row_num
        FROM
          Users,
          Registrations
        WHERE
          Users.ID = Registrations.Timestamp.UserID AND
          Registrations.Date >= '2020-02-27'
        ORDER BY
          Users.ID,
          Registrations.Timestamp) a;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM