【问题标题】:SQL - select rows that have the same value in two columnsSQL - 选择两列中具有相同值的行
【发布时间】:2014-07-14 15:48:27
【问题描述】:

题目的解决方法是在回避我。

我有一个看起来像的表格(除了与我的问题无关的其他字段):

姓名、卡号、会员类型

现在,我想要一个显示卡号和成员类型相同的行的视图。这两个字段都是整数。名称是 VARCHAR。姓名不是唯一的,并且重复的卡号、会员类型也应显示为相同的姓名。

即如果以下是表格:

JOHN       | 324   | 2
PETER      | 642   | 1
MARK       | 324   | 2
DIANNA     | 753   | 2
SPIDERMAN  | 642   | 1
JAMIE FOXX | 235   | 6

我想要:

JOHN       | 324   | 2
MARK       | 324   | 2
PETER      | 642   | 1
SPIDERMAN  | 642   | 1

这可以按卡号排序,以使其对人类有用。

最有效的方法是什么?

【问题讨论】:

  • 你试过select * from <table> where cardnumber = membertype吗?
  • 您列出的记录的 cardnumber 和 membertype 值有何相同之处? 324 != 2
  • 示例清楚地显示了输入和所需的输出。怎么有人糊涂了?
  • 我们很困惑,因为措辞令人困惑、不正确。显然,他的意思是他想要基于这两个字段存在重复行的行。这不是“卡号和会员类型相同的行”。
  • 通过示例,您可以完全忽略措辞。他们为自己说话。

标签: mysql sql join


【解决方案1】:

如果您只需要知道不唯一的 3 个字段的 值对,那么您可以这样做:

SELECT   concat(NAME, "|", CARDNUMBER, "|", MEMBERTYPE) AS myIdentifier, 
         COUNT(*) AS count
FROM     myTable 
GROUP BY myIdentifier
HAVING   count > 1

这将为您提供所有不同的 NAMECARDNUMBERMEMBERTYPE 对,它们被多次使用并计数(它们被重复了多少次)。这不会给您返回条目,您必须在第二步中执行此操作。

【讨论】:

    【解决方案2】:

    由于您提到名字可以重复,并且重复的名字仍然意味着不同的人并且应该出现在结果集中,我们需要使用 GROUP BY HAVING COUNT(*) > 1 才能真正检测到骗子。然后将其加入主表以获取完整的结果列表。

    此外,由于从您的 cmets 中,听起来您正在将其包装到视图中,因此您需要分离出子查询。

    CREATE VIEW DUP_CARDS
    AS
    SELECT CARDNUMBER, MEMBERTYPE
    FROM mytable t2
    GROUP BY CARDNUMBER, MEMBERTYPE
    HAVING COUNT(*) > 1
    
    CREATE VIEW DUP_ROWS
    AS
    SELECT t1.*
    FROM mytable AS t1
    INNER JOIN DUP_CARDS AS DUP
    ON (T1.CARDNUMBER = DUP.CARDNUMBER AND T1.MEMBERTYPE = DUP.MEMBERTYPE )
    

    SQL Fiddle Example

    【讨论】:

    • Table后面的t1和t2是什么意思?像 select 命令的变量一样?
    • 只是表别名。在子查询中将表与自身关联时需要。看here
    • 谢谢。我也会接受你的回答,但这似乎不可能。
    • 如果你喜欢他的回答,可以点赞。我要指出,答案实际上并不合法,您不能使用“table”作为表名。 +1 假设他对此进行了编辑或注释。但是,这两个答案都会跳过名称相同的行。
    • 已编辑答案以反映您的想法,Mrjoltcola。
    【解决方案3】:

    最有效的方法是什么?

    我相信JOIN 会比EXISTS 更有效率

    SELECT t1.* FROM myTable t1
    JOIN (
        SELECT cardnumber, membertype
        FROM myTable
        GROUP BY cardnumber, membertype
        HAVING COUNT(*) > 1
    ) t2 ON t1.cardnumber = t2.cardnumber AND t1.membertype = t2.membertype
    

    查询计划:http://www.sqlfiddle.com/#!2/0abe3/1

    【讨论】:

    • 对不起,我不同意这样更有效率。您已经引入了 GROUP BY,尽管它可能取决于连接。另一个可能是嵌套循环,这是什么?
    • @woot GROUP BY 查询运行一次,因为存在子查询针对表中的每一行运行
    • 鉴于这个问题,我投票认为这是最正确的,因为它包括名称匹配的重复项,我们必须假设这是一种可能性,除非 OP 告诉我们他在所有 3 个列中都有唯一的约束。
    • @nickdnk - 在这种情况下,这是更正确的答案。其他 2 个寻找不同的名称来区分重复的列。如果这是 Oracle,那么 ROWID 或简单的主键将更适合其他答案。
    • 伙计们,这并不比使用exists 更有效。它使用 joingroup by 聚合。查看执行计划,您将看到两者的区别。不过答案很好。
    【解决方案4】:

    您可以为此使用exists

    select * 
    from yourtable y
    where exists (
      select 1
      from yourtable y2 
      where y.name <> y2.name
        and y.cardnumber = y2.cardnumber
        and y.membertype = y2.membertype)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 1970-01-01
      • 2021-02-06
      • 2022-01-01
      相关资源
      最近更新 更多