【问题标题】:SELECT Oracle syntax for getting duplicate records using EXISTS and IN directives使用 EXISTS 和 IN 指令获取重复记录的 SELECT Oracle 语法
【发布时间】:2017-03-20 13:36:22
【问题描述】:

我正在努力处理 SQL 查询,它应该基于这样的表结构:

PID (type VARCHAR)    ATTR (type VARCHAR)
U1                    attribute1
U1                    locale
U2                    attribute1
U2                    locale
U3                    attribute1
U3                    attribute2

我想要做的是选择所有PIDs 在 ATTR 列中没有包含字符串“locale”的记录,因此在我展示的示例中,此查询应返回“U3”

我试过这样的查询:

SELECT DISTINCT PID p
FROM tablename
WHERE NOT EXISTS (SELECT * FROM table
                  WHERE PID = 'p' AND ATTR NOT IN 'locale');

和类似的东西,但我要么没有正确理解 SQL 语法,要么犯了一些其他错误 - 我没有得到正确的结果。

有人知道可能出了什么问题吗?

附:伙计们,我得到了应有的反馈,我一定做错了,请让我补充一些信息,也许会有所帮助。

我所说的表是一个 SAP J2EE 堆栈标准表 (UME_STRINGS),包含用户数据(SAP 术语中的 UME - 用户管理引擎)。它包含除 PID 和 ATTR 之外的许多其他字段,我没有考虑这些字段,因为它们似乎无关紧要。

但是,我需要找到所有没有设置区域设置的用户帐户。由于用户管理显然是“懒惰”的,因此只有在您设置区域设置时才会创建这样的记录(在 ATTR 中具有任意 PID 和值“区域设置”的记录)。这意味着实际上表中有许多用户的任意记录(相同的 PID 值),但在 ATTR 字段中没有一个具有值“locale”。所以算法可能是:

1.)在相同的 PID 上对表进行聚类

2.)遍历集群并检查每个集群内部,如果该集群内的 ATTR 字段中没有带有“locale”的记录,则将此 PID 添加到输出

3.)返回找到 PID 的列表

理想情况下,所有这些都可以通过一个 SQL 查询来完成。

可用的 JAVA API (com.sap.security.api.IUserSearchFilter) 不允许您为搜索设置空值,所以我别无选择,只能直接询问 DB。

除了“语言环境”记录之外当然还有很多其他记录,因为用户、组、角色等的每个属性都是以这种方式建模的——比如 U1 - attribute1 等。

所以我需要的是为我提供用户 PID 的查询,该用户在 ATTR 中没有像“PID - 'locale' 这样的条目。

如果我的描述令人困惑或不完整,请询问。再次感谢

P.P.S.添加了一些带有示例数据和表结构的屏幕截图

【问题讨论】:

  • PID 可以为空吗? (您可以查看您的实际数据:select count(PID) where PID is null)。
  • 不,由于 ER,它总是有一个值集

标签: sql oracle exists


【解决方案1】:

不需要 EXISTS()IN() ,您可以简单地使用带有 CASE EXPRESSIONHAVING 子句:

SELECT t.pid
FROM YourTable t
GROUP BY t.pid
HAVING COUNT(CASE WHEN t.attr = 'locale' THEN 1 END) = 0

【讨论】:

  • 谢谢,听起来不错,但实际上提供了太多数据,U1 和 U2 也是如此。事实上只有U3应该来。也许我做错了什么或忘了提什么?
  • @JohnDoe - 这个答案是正确的(其他一些答案也是正确的)所以你一定做错了什么。请分享一些您认为此查询产生错误结果的数据。
  • 我也有同样的感觉,mathguy,我只代表问题的一个提取物,以保持事情简单。似乎不是一个好主意,我编辑了整个帖子并添加了一些信息,也许会有所帮助
【解决方案2】:

您可以使用非 IN 和子选择

SELECT DISTINCT PID 
FROM tablename
WHERE PID NOT IN (SELECT PID FROM table
                      WHERE  ATTR =  'locale');

最终尝试TRIM(BOTH FROM ATTR)

SELECT DISTINCT PID 
FROM tablename
WHERE PID NOT IN (SELECT PID FROM table
                      WHERE LOWER(TRIM(BOTH  FROM ATTR))=  'locale');

【讨论】:

  • 谢谢,但语法错误,根本无法工作。我在 11g,也许这很重要
  • 抱歉 scaisEdge,提供“未选择行”
  • 如果存在 PID (null) 且 attr = 'locale' 的行,这可能会失败 - 但在这种情况下,它将不返回任何答案,而不是“太多”答案。
  • @mathguy 正确.. 我的回答仅与 OP 提供的数据样本有关
  • PID 不能为空,更改后的查询提供了太多数据。它似乎还包括 U1 和 U2 数据,我假设除了 U1 - 语言环境、U2 - 语言环境等之外的任何内容。我需要相当单一的 PID 值,它在同一个表中没有记录,如 PID - 语言环境
【解决方案3】:

你可以这样做

SELECT DISTINCT PID
FROM tableName
WHERE PID NOT IN (SELECT PID FROM tableName WHERE Attr = 'locale')

【讨论】:

  • 谢谢,但提供了太多数据,类似于 sagi 的回答。我希望成为唯一的值,它在 ATTR 中没有具有任意 PID 和“区域设置”值的记录。在我的示例中,这将是 U3
  • 上述查询仅返回 U3,因为 U2 和 U1 的行具有 Attr 值作为语言环境
  • 如果我在我的机器(Oracle 11g,Win 2008 R2 服务器)上运行查询,无论如何,谢谢。我觉得我的场景不完整,我在整个帖子中添加了一些信息,请随时询问您是否遗漏了什么
  • @JohnDoe 请再次编辑您的帖子并添加您现在正在运行但不起作用的查询。
  • sagi,这很简单 - 建议的查询都没有为我工作 :) 我假设它是第 8 层问题,但我无法弄清楚我做错了什么。我已经完成了整个问题描述,现在非常直截了当,恕我直言,如果您遗漏了什么 - 请告诉我,谢谢
【解决方案4】:
SELECT DISTINCT PID p
FROM tablename t
WHERE NOT EXISTS (SELECT * FROM tablename t2
                  WHERE t2.PID = t.PID AND t2.ATTR = 'locale');

【讨论】:

  • 谢谢,但提供“未选择行”
  • 应该是... WHERE NOT EXISTS (SELECT * FROM tablename t2 WHERE t2.PID = t.PID AND t2.ATTR = 'locale');
  • 谢谢,但与其他答案类似,它提供了太多数据 - 显然还有像 U1 - attribute1 这样的记录,我们不想这样做
【解决方案5】:

试试这个。其他一些查询的问题是 not exists 仅查找 attr 语言环境,没有通过 PID 加入。

select t1.pid from tablename t1
where not exists 
(select t2.pid from tablename t2 where t2.pid=t1.pid and    t2.attr='locale');

【讨论】:

    猜你喜欢
    • 2011-01-30
    • 2020-01-20
    • 1970-01-01
    • 2013-03-30
    • 2015-07-18
    • 2013-05-09
    • 2013-12-23
    • 2020-03-25
    相关资源
    最近更新 更多