Select 所有具有特定特征的行,通过在 oracle 中通过相同的行值对它们进行分组,具有相同的子数据
Select all rows, with specific characteristics, with same subdata by grouping them through a same row value in oracle
我有一个 table 具有下一个结构:
Data structure:
| CONTRACT | CONNECTION | STATE |
| 1 | AAA | Y |
| 2 | AAA | Y |
| 3 | BBB | N |
| 4 | BBB | N |
| 5 | BBB | N |
| 6 | BBB | N |
| 7 | AAA | Y |
| 8 | CCC | Y |
| 9 | CCC | N |
| 10 | AAA | Y |
| 11 | CCC | N |
我想 select 所有 rows/data 考虑到由 CONNECTION 列定义为组 AAA、BBB 和 CCC 的组,查询必须 select 只有具有具有值 'N' 的 STATE 列的 all 行,但始终考虑该组的所有数据。
所以 table 的结果将是:
Result needed:
| CONTRACT | CONNECTION | STATE |
| 3 | BBB | N |
| 4 | BBB | N |
| 5 | BBB | N |
| 6 | BBB | N |
我一直在寻找解码、存在等函数,但就是不知道如何解决这个问题。
知道如何为此目的编写查询吗?
您可以使用 SUM
和 HAVING
:
SELECT *
FROM tbl t
WHERE
CONNECTION IN(
SELECT CONNECTION
FROM tbl
GROUP BY CONNECTION
HAVING
SUM(CASE WHEN STATE = 'N' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN STATE <> 'N' THEN 1 ELSE 0 END) = 0
)
HAVING
子句中的第一个条件确保 CONNECTION
至少有一个 STATE = 'N'
。第二个确保 CONNECTION
除了 'N'
.
没有其他 STATE
试试这个:
SELECT CONTRACT, CONNECTION, STATE
FROM (
SELECT CONTRACT, CONNECTION, STATE,
COUNT(CASE WHEN STATE <> 'N' THEN 1 END) OVER (PARTITION BY CONNECTION) AS cnt
FROM mytable) t
WHERE t.cnt = 0
你可以使用窗口化 COUNT
:
WITH cte AS (
SELECT *
,COUNT(CASE WHEN STATE = 'N' THEN 1 END) OVER(PARTITION BY CONNECTION) AS num_of_n
,COUNT(CASE WHEN STATE <> 'N' OR STATE IS NULL THEN 1 END)
OVER(PARTITION BY CONNECTION) AS num_of_non_n
FROM mytable
)
SELECT CONTRACT, CONNECTION, STATE
FROM cte
WHERE num_of_n > 0 AND num_of_non_n = 0;
或相关子查询:
SELECT *
FROM mytable m1
WHERE STATE = 'N'
AND NOT EXISTS (SELECT 1
FROM mytable m2
WHERE m1.CONNECTION = m2.CONNECTION
AND (STATE <> 'N' OR STATE IS NULL));
我有一个 table 具有下一个结构:
Data structure:
| CONTRACT | CONNECTION | STATE |
| 1 | AAA | Y |
| 2 | AAA | Y |
| 3 | BBB | N |
| 4 | BBB | N |
| 5 | BBB | N |
| 6 | BBB | N |
| 7 | AAA | Y |
| 8 | CCC | Y |
| 9 | CCC | N |
| 10 | AAA | Y |
| 11 | CCC | N |
我想 select 所有 rows/data 考虑到由 CONNECTION 列定义为组 AAA、BBB 和 CCC 的组,查询必须 select 只有具有具有值 'N' 的 STATE 列的 all 行,但始终考虑该组的所有数据。 所以 table 的结果将是:
Result needed:
| CONTRACT | CONNECTION | STATE |
| 3 | BBB | N |
| 4 | BBB | N |
| 5 | BBB | N |
| 6 | BBB | N |
我一直在寻找解码、存在等函数,但就是不知道如何解决这个问题。
知道如何为此目的编写查询吗?
您可以使用 SUM
和 HAVING
:
SELECT *
FROM tbl t
WHERE
CONNECTION IN(
SELECT CONNECTION
FROM tbl
GROUP BY CONNECTION
HAVING
SUM(CASE WHEN STATE = 'N' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN STATE <> 'N' THEN 1 ELSE 0 END) = 0
)
HAVING
子句中的第一个条件确保 CONNECTION
至少有一个 STATE = 'N'
。第二个确保 CONNECTION
除了 'N'
.
STATE
试试这个:
SELECT CONTRACT, CONNECTION, STATE
FROM (
SELECT CONTRACT, CONNECTION, STATE,
COUNT(CASE WHEN STATE <> 'N' THEN 1 END) OVER (PARTITION BY CONNECTION) AS cnt
FROM mytable) t
WHERE t.cnt = 0
你可以使用窗口化 COUNT
:
WITH cte AS (
SELECT *
,COUNT(CASE WHEN STATE = 'N' THEN 1 END) OVER(PARTITION BY CONNECTION) AS num_of_n
,COUNT(CASE WHEN STATE <> 'N' OR STATE IS NULL THEN 1 END)
OVER(PARTITION BY CONNECTION) AS num_of_non_n
FROM mytable
)
SELECT CONTRACT, CONNECTION, STATE
FROM cte
WHERE num_of_n > 0 AND num_of_non_n = 0;
或相关子查询:
SELECT *
FROM mytable m1
WHERE STATE = 'N'
AND NOT EXISTS (SELECT 1
FROM mytable m2
WHERE m1.CONNECTION = m2.CONNECTION
AND (STATE <> 'N' OR STATE IS NULL));