SQL 使用 N-1 Dense Rank 过滤掉 dense rank N Mysql 中的行
SQL using N-1 Dense Rank to filter out rows in dense rank N Mysql
如果我的标题不清楚,这里有一个我正在谈论的例子。
假设我有一个 table 看起来像这样:
+----+------+----+----+---------+-------+---------+-------+
| ID | Time | X | Y | X_START | X_END | Y_START | Y_END |
+----+------+----+----+---------+-------+---------+-------+
| 1 | 0 | 8 | 6 | 6 | 10 | 4 | 8 |
| 2 | 0 | 20 | 10 | 18 | 22 | 8 | 12 |
| 3 | 1 | 8 | 8 | 6 | 10 | 6 | 10 |
| 4 | 1 | 10 | 24 | 8 | 12 | 22 | 26 |
+----+------+----+----+---------+-------+---------+-------+
如果我将此查询应用于 table:
WITH
cte1 AS (SELECT *,
DENSE_RANK() OVER (ORDER BY TIME) AS DENSE_RANK
FROM data
ORDER BY TIME)
SELECT * FROM cte1
我得到:
+----+------+----+----+---------+-------+---------+-------+------------+
| ID | Time | X | Y | X_START | X_END | Y_START | Y_END | DENSE_RANK |
+----+------+----+----+---------+-------+---------+-------+------------+
| 1 | 0 | 8 | 6 | 6 | 10 | 4 | 8 | 1 |
| 2 | 0 | 20 | 10 | 18 | 22 | 8 | 12 | 1 |
| 3 | 1 | 8 | 8 | 6 | 10 | 6 | 10 | 2 |
| 4 | 1 | 10 | 24 | 8 | 12 | 22 | 26 | 2 |
+----+------+----+----+---------+-------+---------+-------+------------+
现在我要做的是过滤掉 X 在 X_START - X_END 范围内并且 Y 在 Y_START - Y_END 范围内的任何行AND DENSE_RANK 是 n-1
所以我想要这样的结果:
+----+------+----+----+---------+-------+---------+-------+------------+
| ID | Time | X | Y | X_START | X_END | Y_START | Y_END | DENSE_RANK |
+----+------+----+----+---------+-------+---------+-------+------------+
| 1 | 0 | 8 | 6 | 6 | 10 | 4 | 8 | 1 |
| 2 | 0 | 20 | 10 | 18 | 22 | 8 | 12 | 1 |
| 4 | 1 | 10 | 24 | 8 | 12 | 22 | 26 | 2 |
+----+------+----+----+---------+-------+---------+-------+------------+
我是 SQL 的新手,所以我不太确定该怎么做。预先感谢您的所有帮助!
使用 MIN()
window 函数确定每个 Time
的最小值 ID
以便在所有其他条件都满足的情况下排除该行:
WITH cte AS (
SELECT *,
DENSE_RANK() OVER (ORDER BY TIME) AS `DENSE_RANK`,
MIN(ID) OVER (PARTITION BY TIME) min_id
FROM data
)
SELECT ID, Time, X, Y, X_START, X_END, Y_START, Y_END, `DENSE_RANK`
FROM cte
WHERE `DENSE_RANK` = 1
OR NOT (ID = min_id AND X BETWEEN X_START AND X_END AND Y BETWEEN Y_START AND Y_END)
ORDER BY `DENSE_RANK`, ID;
参见demo。
如果我的标题不清楚,这里有一个我正在谈论的例子。
假设我有一个 table 看起来像这样:
+----+------+----+----+---------+-------+---------+-------+
| ID | Time | X | Y | X_START | X_END | Y_START | Y_END |
+----+------+----+----+---------+-------+---------+-------+
| 1 | 0 | 8 | 6 | 6 | 10 | 4 | 8 |
| 2 | 0 | 20 | 10 | 18 | 22 | 8 | 12 |
| 3 | 1 | 8 | 8 | 6 | 10 | 6 | 10 |
| 4 | 1 | 10 | 24 | 8 | 12 | 22 | 26 |
+----+------+----+----+---------+-------+---------+-------+
如果我将此查询应用于 table:
WITH
cte1 AS (SELECT *,
DENSE_RANK() OVER (ORDER BY TIME) AS DENSE_RANK
FROM data
ORDER BY TIME)
SELECT * FROM cte1
我得到:
+----+------+----+----+---------+-------+---------+-------+------------+
| ID | Time | X | Y | X_START | X_END | Y_START | Y_END | DENSE_RANK |
+----+------+----+----+---------+-------+---------+-------+------------+
| 1 | 0 | 8 | 6 | 6 | 10 | 4 | 8 | 1 |
| 2 | 0 | 20 | 10 | 18 | 22 | 8 | 12 | 1 |
| 3 | 1 | 8 | 8 | 6 | 10 | 6 | 10 | 2 |
| 4 | 1 | 10 | 24 | 8 | 12 | 22 | 26 | 2 |
+----+------+----+----+---------+-------+---------+-------+------------+
现在我要做的是过滤掉 X 在 X_START - X_END 范围内并且 Y 在 Y_START - Y_END 范围内的任何行AND DENSE_RANK 是 n-1
所以我想要这样的结果:
+----+------+----+----+---------+-------+---------+-------+------------+
| ID | Time | X | Y | X_START | X_END | Y_START | Y_END | DENSE_RANK |
+----+------+----+----+---------+-------+---------+-------+------------+
| 1 | 0 | 8 | 6 | 6 | 10 | 4 | 8 | 1 |
| 2 | 0 | 20 | 10 | 18 | 22 | 8 | 12 | 1 |
| 4 | 1 | 10 | 24 | 8 | 12 | 22 | 26 | 2 |
+----+------+----+----+---------+-------+---------+-------+------------+
我是 SQL 的新手,所以我不太确定该怎么做。预先感谢您的所有帮助!
使用 MIN()
window 函数确定每个 Time
的最小值 ID
以便在所有其他条件都满足的情况下排除该行:
WITH cte AS (
SELECT *,
DENSE_RANK() OVER (ORDER BY TIME) AS `DENSE_RANK`,
MIN(ID) OVER (PARTITION BY TIME) min_id
FROM data
)
SELECT ID, Time, X, Y, X_START, X_END, Y_START, Y_END, `DENSE_RANK`
FROM cte
WHERE `DENSE_RANK` = 1
OR NOT (ID = min_id AND X BETWEEN X_START AND X_END AND Y BETWEEN Y_START AND Y_END)
ORDER BY `DENSE_RANK`, ID;
参见demo。