【问题标题】:How to select distinct records with where conditions without using sub queries如何在不使用子查询的情况下选择具有 where 条件的不同记录
【发布时间】:2018-01-06 19:11:18
【问题描述】:

我有一个具有以下架构的表

(Id(int PK),EmployeeId(int),DepartmentId(int),IsSelfAccessToDepartment(bit))

此表可以包含以下条目

(1,101,21,1)
(2,101,22,0)
(3,102,21,1)
(4,103,21,1)
(5,103,22,0)

我只想检索 IsSelfAccessToDepartment=1 的员工 ID,即如果同一员工 ID 有另一个条目 IsSelfAccessToDepartment=0,在这种情况下不应检索此行。

问题是我想在不使用任何子查询和连接的情况下检索此信息,因为它会产生性能问题,因为此表将包含数百万个条目。

【问题讨论】:

  • mysql 还是 sql server?
  • select * from table_name where IsSelfAccessToDepartment=1;
  • @JYoThI 是的,但他说他只想要他们的 id 只有一行的员工,其值为 1。也就是说,他不想看到有 2 行的员工
  • 这是一个基本的 SQL 查询 where 条件。为什么还要考虑使用子查询?你也尝试过什么?
  • @MenelaosBakopoulos 他想要一个只包含“102”的结果集;他根本不想为“101”和“103”返回行

标签: mysql sql sql-server database


【解决方案1】:

这样的东西适用于 MySQL 或 SQLServer:

SELECT employeeID FROM table GROUP BY employeeID
HAVING MIN(IsSelfAccessToDepartment) = 1 AND MAX(IsSelfAccessToDepartment) = 1

这只会让您获得员工 ID;如果需要,您可以添加部门 ID。实际上,您最终会加入此信息以从中获取有用的信息。另外,从您的示例中,您并不清楚在员工有 3 行的情况下您期望什么

我会使用 ROW_NUMBER() OVER() 但 MySQL 不支持它。

请正确标记您的问题以反映您正在使用的数据库

【讨论】:

    【解决方案2】:

    Min 函数应该用于过滤掉所有条目为 0 的员工。 还应利用 Max 函数将条目限制为不高于 1。

    SELECT employeeID, MIN(IsSelfAccessToDepartment) FROM test2 GROUP BY employeeID
    HAVING MIN(isSelfAccessToDepartment) = 1;
    

    最后:

    • 不需要计数,因为这不是 OP 要求的要求
    • 如果IsSelfAccessToDepartment 不多,则可以添加代码AND MAX(isSelfAccessToDepartment) = 1。但是,有点像,两个可用值是零和一(感谢@Caius 在 cmets 中的这一点)。

    此外,还有其他创造性的解决方案(但效率低下),例如:

    SELECT employeeID FROM test2 GROUP BY employeeID
    HAVING SUM(isSelfAccessToDepartment) = COUNT(isSelfAccessToDepartment);
    

    此假设 isSelfAccessToDepartment 可以为零或 1。如果不存在零条目,则总和将与计数相同。

    【讨论】:

    • 这就是堆栈溢出的糟糕之处;你编辑你的答案抄袭我的,你得到了它的分数..(特别是看到一开始你甚至看不到如何回答这个问题)
    • @Caius Jard 你最初的回答是错误的。我的回答更正确。在此处查看编辑证明:i.prntscr.com/DEoUK2dVTjmJpjbjDpACMA.png。您使用了 MAX 而不是 MIN。修订:stackoverflow.com/posts/45412283/revisionsstackoverflow.com/posts/45412248/revisions
    • 我使用了 count 和 max,这在问题的上下文中并没有错,但后来我将其修改为 min 和 max,因为 COUNT(*) 将使用 3 行的未指定示例导致错误。您只使用了 min .. 在我评论了您的答案之后,您编辑了您的答案以克隆我的答案!试图摆脱它并没有多大意义 - 你的第一个答案很好顺便说一句 - MAX 对于 BIT 数据类型是多余的;)所以你真的可以单独留下你的答案,而不是复制别人的
    • COUNT(*) = 1 在OP给出的示例中没有错;他希望员工记录只出现一次,而不是 0。如果某人出现两次(一次为 1,一次为 0),则 COUNT/MAX 会删除这些人。在考虑到可能会导致问题的其他情况(3x emps)后,我转而使用 MIN。我接受您的说法,即 MIN 是实现相同目标的更简单方法,我什至最初称赞您的解决方案仅使用 MIN。不太清楚为什么,在我这样做后不久,你认为我的 MIN/MAX 答案适合你,但是嘿;你知道你偷了什么
    • 用“适当的解决方案”华夫饼戒掉它。给猫剥皮的方法总是不止一种。 count/max 的逻辑是合理的:“只有一名员工,他们的最大值为 1”可以确保只有一行员工的值为 1。几乎可以使用任何聚合函数(sum、avg 等。由于计数,如果只有一行,它们都可以工作)。这就是 OP 要求的全部内容,在我向您解释之前您无法理解。所有这些外围讨论都围绕着一个甚至可能不存在的想象情况
    【解决方案3】:

    如果您的 DBMS 是 MySQL

    一个简单的GROUP BY 和一个HAVINGCOUNT 这样做

    SELECT Id, EmployeeID, DepartmentId, IsSelfAccessToDepartment
    FROM yourtable
    GROUP BY EmployeeId
    HAVING IsSelfAccessToDepartment = 1
    AND COUNT(EmployeeID) = 1
    

    输出

    Id  EmployeeID  DepartmentId    IsSelfAccessToDepartment
    3   102         21              1
    

    SQL 小提琴:http://sqlfiddle.com/#!9/7a75b8/1/0

    如果您的 DBMS 是 SQL Server

    SELECT MIN(Id) AS Id, EmployeeID, MIN(DepartmentId) AS DepartmentId, MIN(IsSelfAccessToDepartment) AS IsSelfAccessToDepartment
    FROM yourtable
    GROUP BY EmployeeId
    HAVING MIN(IsSelfAccessToDepartment) = 1
    AND COUNT(EmployeeID) = 1
    

    输出

    Id  EmployeeID  DepartmentId    IsSelfAccessToDepartment
    3   102         21              1
    

    SQL 小提琴:http://sqlfiddle.com/#!6/3b4ef/4/0

    【讨论】:

    • 如果员工 104 只有一行 (6,104,21,0) 怎么办?
    • 因为 HAVING IsSelfAccessToDepartment = 1 它不会显示,我已经更新了我的 SQL Fiddle 来显示这个。
    • 哈,我完全错过了那条线,但后来我看了看,想“这到底是怎么回事?” - 我不知道 MySQL(你的 sql fiddle)中发生了什么自动幕后的东西,但这种查询在 SQLServer 中不起作用,因为你选择的几个列在 group by 中没有提到。它会给出一个错误,例如“xxx 在 SELECT / HAVING 子句中无效,因为它不包含在 group by 中”
    • @CaiusJard 还包含一个 SQL Server 答案。
    • 这种查询模式是危险的,因为通常用户需要基于某些条件的特定数据行,但是在那里放置大量 MIN 并不能保证所有可见数据都来自同一行..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多