5

对于令人困惑的标题,我深表歉意,我无法弄清楚这个问题的正确措辞。相反,我只会给你背景信息和目标:

这是在一个人可能有也可能没有多行数据的表中,这些行可能包含相同的值activity_id,也可能没有。每行都有一个自动递增的 ID。人们的名字没有附加唯一标识符,因此我们只能使用 first_name/last_name 来识别一个人。

我需要能够在此表中找到具有多行的人,但只有具有包含多个不同行的人activity_id

这是我们正在查看的数据示例:

unique_id | first_name    |   last_name    |    activity_id
---------------------------------------------------------------
 1        | ted           | stevens        | 544
 2        | ted           | stevens        | 544
 3        | ted           | stevens        | 545
 4        | ted           | stevens        | 546
 5        | rachel        | jameson        | 633
 6        | jennifer      | tyler          | 644
 7        | jennifer      | tyler          | 655
 8        | jennifer      | tyler          | 655
 9        | jack          | fillion        | 544
 10       | mallory       | taylor         | 633
 11       | mallory       | taylor         | 633

从那个小样本中,这是我想要返回的记录:

unique_id | first_name    |   last_name    |    activity_id
---------------------------------------------------------------
 dontcare | ted           | stevens        | 544
 dontcare | jennifer      | tyler          | 655

请注意,返回哪个值unique_id是无关紧要的,只要它是unique_id属于该人的 s 之一,并且只要为该人返回一条记录。

谁能弄清楚如何编写这样的查询?我不在乎你使用什么版本的 SQL,如果它有什么不同,我可能可以将它翻译成 Oracle。

4

4 回答 4

9

我会做:

SELECT first_name, last_name, COUNT(DISTINCT activity_id)
FROM <table_name>
GROUP BY first_name, last_name
HAVING COUNT(DISTINCT activity_id) > 0;
于 2013-09-11T21:41:33.023 回答
2

我会和你一起建立逻辑。首先,让我们找出所有拥有多个条目的人:

名称+活动ID的唯一列表:

select first_name, last_name,activity_id, count(1)
from yourtable
group by first_name, last_name,activity_id

现在我们将它变成一个子查询并寻找具有超过 1 个 activity_ID 的用户

Select first_name, last_name
from 
    (select first_name, last_name,activity_id, count(1)
    from yourtable
    group by first_name, last_name,activity_id) a
group by  first_name, last_name
having count(1) > 1

应该那样工作...我没有返回activity_id,将max(activity_id)添加到select语句将获取最高的。

于 2013-09-11T21:42:55.207 回答
0

要仅获取名称,最简单的是:

SELECT 
    first_name
  , last_name 
FROM 
    person
GROUP BY 
    first_name
  , last_name
HAVING 
    COUNT(DISTINCT activity_id) >= 2 ;

要为每个名称获取一行,您可以使用窗口函数(在 Oracle 中工作正常):

WITH cte AS
  ( SELECT 
        unique_id, first_name, last_name, activity_id
      , COUNT(DISTINCT activity_id) OVER (PARTITION BY last_name, first_name)
          AS cnt 
      , MIN(unique_id) OVER (PARTITION BY last_name, first_name)
          AS min_id 
    FROM 
        person
  )
SELECT
    unique_id, first_name, last_name, activity_id
FROM 
    cte
WHERE
    cnt >= 2
  AND
    min_id = unique_id ;

代替MIN(unique_id) OVER ...,您可以使用MIN(activity_id) OVER ...(或MAX()) 并相应地使用min_id = activity_id。或ROW_NUMBER()功能。既然你COUNT(DISTINCT activity_id)无论如何都需要,让我添加这个版本。

使用索引(last_name, first_name, activity_id, unique_id)应该非常有效:

WITH cte AS
  ( SELECT 
        unique_id, first_name, last_name, activity_id
      , COUNT(DISTINCT activity_id) OVER (PARTITION BY last_name, first_name)
          AS cnt 
      , ROW_NUMBER() OVER (PARTITION BY last_name, first_name 
                           ORDER BY activity_id, unique_id)
          AS rown 
    FROM 
        person
  )
SELECT
    unique_id, first_name, last_name, activity_id
FROM 
    cte
WHERE
    cnt >= 2
  AND
    rown = 1 ;

SQL-Fiddle测试

于 2013-09-11T23:03:04.347 回答
0

请注意,返回哪个 unique_id 的值是无关紧要的,只要它是属于该人的 unique_id 之一,并且只要为该人返回一条记录。

这些查询应该可以解决问题。不需要不同的关键字或子查询来获取 BumbleShrimp 需要的结果(如果 BumbleShrimp 需要正确的 unique_id 也需要子查询来匹配正确的值)

下面是我能想到的最简单的查询,它应该可以工作,但在大表上可能会很慢。

SELECT 
   first_name
 , last_name 
 , activity_id
FROM 
 person
GROUP BY 
   first_name
 , last_name
 , activity_id
HAVING COUNT(*) >= 2

可能会很慢,因为解释显示“使用索引;使用临时;使用文件排序”。使用临时表可能会触发基于磁盘的临时表,因此我们使用内部自连接来消除使用临时表的需要。

SELECT 
   person1.first_name
 , person1.last_name
 , person1.activity_id
FROM 
 person person1
INNER JOIN
 person person2

ON
 person1.unique_id < person2.unique_id
AND 
 person1.first_name = person2.first_name
AND 
 person1.last_name = person2.last_name
AND 
 person1.activity_id = person2.activity_id

ORDER BY 
    activity_id asc

见演示http://sqlfiddle.com/#!2/fe3ba/29

旁注如果存在三个或更多重复项,则内部连接将失败, 请参见演示http://sqlfiddle.com/#!2/1ff33/15

新查询

SELECT 
   first_name
 , last_name 
 , activity_id
FROM 
 person
GROUP BY 
   activity_id
 , last_name
 , first_name
HAVING COUNT(activity_id) >= 2
ORDER BY 
 activity_id asc

请参阅演示http://sqlfiddle.com/#!2/1e418/3修复了三个或更多重复问题/命令 activity_id 正确,并且可以在大型表上使用,因为不需要关闭临时表会减慢执行速度

于 2013-09-11T22:41:20.503 回答