SQL - 选择两列中具有相同值的行
Posted
技术标签:
【中文标题】SQL - 选择两列中具有相同值的行【英文标题】:SQL - select rows that have the same value in two columns 【发布时间】: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
示例清楚地显示了输入和所需的输出。怎么有人糊涂了?
我们很困惑,因为措辞令人困惑、不正确。显然,他的意思是他想要基于这两个字段存在重复行的行。这不是“卡号和会员类型相同的行”。
通过示例,您可以完全忽略措辞。他们为自己说话。
【参考方案1】:
如果您只需要知道不唯一的 3 个字段的 值对,那么您可以这样做:
SELECT concat(NAME, "|", CARDNUMBER, "|", MEMBERTYPE) AS myIdentifier,
COUNT(*) AS count
FROM myTable
GROUP BY myIdentifier
HAVING count > 1
这将为您提供所有不同的 NAME
、CARDNUMBER
和 MEMBERTYPE
对,它们被多次使用并计数(它们被重复了多少次)。这不会给您返回条目,您必须在第二步中执行此操作。
【讨论】:
【参考方案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,尽管它可能取决于连接。另一个可能是嵌套循环,这是什么? @wootGROUP BY
查询运行一次,因为存在子查询针对表中的每一行运行
鉴于这个问题,我投票认为这是最正确的,因为它包括名称匹配的重复项,我们必须假设这是一种可能性,除非 OP 告诉我们他在所有 3 个列中都有唯一的约束。
@nickdnk - 在这种情况下,这是更正确的答案。其他 2 个寻找不同的名称来区分重复的列。如果这是 Oracle,那么 ROWID 或简单的主键将更适合其他答案。
伙计们,这并不比使用exists
更有效。它使用 join
和 group 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)
SQL Fiddle Demo
【讨论】:
以上是关于SQL - 选择两列中具有相同值的行的主要内容,如果未能解决你的问题,请参考以下文章