关系部门 - 模仿 'ONLY IN'
Relational Division - Mimicking 'ONLY IN'
我正在尝试在 Oracle SQL 中编写一个查询,该查询采用两个参数并在整个 table 中查找所有只出现 or 的实例,而不管它们有多少在搜索范围内。这是我正在寻找的示例:
| ID | FileType | COUNT(FileType) |
|-----|----------|-----------------|
| 1 | txt | 1 |
| 1 | png | 3 |
| 1 | jpg | 2 |
====================================
| 2 | txt | 0 |
| 2 | png | 6 |
| 2 | jpg | 0 |
====================================
| 3 | txt | 0 |
| 3 | png | 0 |
| 3 | jpg | 5 |
====================================
| 4 | txt | 0 |
| 4 | png | 3 |
| 4 | jpg | 1 |
====================================
| 5 | txt | 5 |
| 5 | png | 0 |
| 5 | jpg | 3 |
我的目标是获取所有仅包含 png 或 jpg 的 ID,并忽略其余部分,因此我只希望返回 ID 2、3 和 4。
我已尝试在此处查找解决方案,但没有找到任何似乎符合我的情况的解决方案。
(最接近这个问题:SQL select rows with only a certain value in them)
我确实设法发现问题可以通过关系划分来解决,但到目前为止我还没有任何经验。到目前为止,我的查询如下所示:
SELECT DISTINCT ID, FileType, COUNT(FileType)
FROM Table ta
WHERE (ta.FileType = 'jpg' or ta.FileType = 'png') and
NOT EXISTS
(SELECT *
FROM Table tb
WHERE ta.FileType = tb.FileType and
(tb.FileType != 'jpg' or tb.FileType != 'png'))
GROUP BY ID, FileType;
当我尝试这个时,我没有得到任何结果。有人知道我哪里出错了吗?
你很接近。看看你有多少不同的文件类型。这是您的 ID:
SELECT ID
FROM Table ta
GROUP BY ID
HAVING count(distinct FileType) = 1 and max(ta.FileType) in ('jpg','png');
更新:案例 4 鞋帮会失败。
这样就可以了,但是很丑:
SELECT ID
FROM Table ta
GROUP BY ID
HAVING count(distinct FileType) <= 2
and max(ta.FileType) in ('jpg','png')
and min(ta.FileType) in ('jpg','png');
它很难看,因为您不能将它扩展为 3 个值。
您可以使用集合运算符:
SELECT ID FROM tab WHERE FileType IN ('jpg', 'png')
MINUS
SELECT ID FROM tab WHERE FileType NOT IN ('jpg', 'png')
假设:FileType 不可为空。
处理 NULL:
SELECT ID FROM tab WHERE FileType IN ('jpg', 'png')
MINUS
SELECT ID
FROM (SELECT * FROM tab WHERE FileType IS NOT NULL)
WHERE FileType NOT IN ('jpg', 'png')
只需使用 "helper" table:
WITH TypeCounts AS
(
SELECT ID, FileType, COUNT(*) AS CNT
FROM Table
GROUP BY ID, FileType
)
SELECT *
FROM Table
LEFT JOIN TypeCounts txt ON txt.ID = Table.ID AND txt.FileType = 'txt'
LEFT JOIN TypeCounts jpg ON jpg.ID = Table.ID AND jpg.FileType = 'jpg'
LEFT JOIN TypeCounts png ON png.ID = Table.ID AND png.FileType = 'png'
WHERE COALESCE(txt.CNT,0) = 0 AND
( COALESCE(jpg.CNT,0) > 0 OR COALESCE(png.CNT,0) > 0)
此解决方案的好处在于,它非常清楚业务规则是什么,因此更易于维护。
我正在尝试在 Oracle SQL 中编写一个查询,该查询采用两个参数并在整个 table 中查找所有只出现 or 的实例,而不管它们有多少在搜索范围内。这是我正在寻找的示例:
| ID | FileType | COUNT(FileType) |
|-----|----------|-----------------|
| 1 | txt | 1 |
| 1 | png | 3 |
| 1 | jpg | 2 |
====================================
| 2 | txt | 0 |
| 2 | png | 6 |
| 2 | jpg | 0 |
====================================
| 3 | txt | 0 |
| 3 | png | 0 |
| 3 | jpg | 5 |
====================================
| 4 | txt | 0 |
| 4 | png | 3 |
| 4 | jpg | 1 |
====================================
| 5 | txt | 5 |
| 5 | png | 0 |
| 5 | jpg | 3 |
我的目标是获取所有仅包含 png 或 jpg 的 ID,并忽略其余部分,因此我只希望返回 ID 2、3 和 4。
我已尝试在此处查找解决方案,但没有找到任何似乎符合我的情况的解决方案。 (最接近这个问题:SQL select rows with only a certain value in them)
我确实设法发现问题可以通过关系划分来解决,但到目前为止我还没有任何经验。到目前为止,我的查询如下所示:
SELECT DISTINCT ID, FileType, COUNT(FileType)
FROM Table ta
WHERE (ta.FileType = 'jpg' or ta.FileType = 'png') and
NOT EXISTS
(SELECT *
FROM Table tb
WHERE ta.FileType = tb.FileType and
(tb.FileType != 'jpg' or tb.FileType != 'png'))
GROUP BY ID, FileType;
当我尝试这个时,我没有得到任何结果。有人知道我哪里出错了吗?
你很接近。看看你有多少不同的文件类型。这是您的 ID:
SELECT ID
FROM Table ta
GROUP BY ID
HAVING count(distinct FileType) = 1 and max(ta.FileType) in ('jpg','png');
更新:案例 4 鞋帮会失败。
这样就可以了,但是很丑:
SELECT ID
FROM Table ta
GROUP BY ID
HAVING count(distinct FileType) <= 2
and max(ta.FileType) in ('jpg','png')
and min(ta.FileType) in ('jpg','png');
它很难看,因为您不能将它扩展为 3 个值。
您可以使用集合运算符:
SELECT ID FROM tab WHERE FileType IN ('jpg', 'png')
MINUS
SELECT ID FROM tab WHERE FileType NOT IN ('jpg', 'png')
假设:FileType 不可为空。
处理 NULL:
SELECT ID FROM tab WHERE FileType IN ('jpg', 'png')
MINUS
SELECT ID
FROM (SELECT * FROM tab WHERE FileType IS NOT NULL)
WHERE FileType NOT IN ('jpg', 'png')
只需使用 "helper" table:
WITH TypeCounts AS
(
SELECT ID, FileType, COUNT(*) AS CNT
FROM Table
GROUP BY ID, FileType
)
SELECT *
FROM Table
LEFT JOIN TypeCounts txt ON txt.ID = Table.ID AND txt.FileType = 'txt'
LEFT JOIN TypeCounts jpg ON jpg.ID = Table.ID AND jpg.FileType = 'jpg'
LEFT JOIN TypeCounts png ON png.ID = Table.ID AND png.FileType = 'png'
WHERE COALESCE(txt.CNT,0) = 0 AND
( COALESCE(jpg.CNT,0) > 0 OR COALESCE(png.CNT,0) > 0)
此解决方案的好处在于,它非常清楚业务规则是什么,因此更易于维护。