SQL返回第1列包含X和Y的行

时间:2014-03-19 20:17:40

标签: mysql sql return duplicates

我知道这必须在SQL 101中,但我需要返回一行,其中一列包含X和Y,其中ID是重复的。

示例表。

 ACCOUNT   |   Activity
-------------------------
   1       |   Email
   1       |   Appointment
   2       |   Email
   2       |   Email
   3       |   Email
   3       |   Appointment

我需要只返回帐号1和3的SQL,如下所示:

 ACCOUNT   |   Activity
-------------------------
   1       |   Email
   1       |   Appointment
   3       |   Email
   3       |   Appointment

在伪代码中它是(WHERE ID同时出现'约会'和'电子邮件')

不应该返回帐户2,因为表格中没有行WHERE Account = 2 AND Activity ='Appointment'。

我希望这是有道理的,并且非常感谢您的意见。

提前感谢。

编辑线以下


感谢大家的建议,我非常喜欢@rafa建议使用count distinct,但当然查询比最初建议的更复杂。第一个表实际上是来自另一个查询的结果集,下面的查询包括@rafa建议,但查询不起作用,我理解我需要调用子查询,但我不确定在哪里或如何,再次感谢:

SELECT T.ACCOUNT, T.COMPANY, H.RESPONSE, H.DAT_ AS Resp_Date, H.USERNAME, (date_format(P.ENDDATE,'%M')) AS Renewal, T.OWNER, COUNT(DISTINCT(H.ACTIVITY)) AS Dis_Act, H.CustomerStatus, H.Contact, A.ANAL14 AS APPDATE
FROM TELRCMxxx T LEFT JOIN TELCOMxxx H ON T.ACCOUNT = H.ACCOUNT LEFT JOIN ACCSTOxxx P ON T.ACCOUNT = P.ACCOUNT LEFT JOIN RCMANLxxx A ON T.ACCOUNT = A.ACCOUNT
WHERE (H.ACTIVITY in ('Appointment', 'email'))
Group by Account 
having Dis_Act > 1

学家


谢谢大家。

8 个答案:

答案 0 :(得分:1)

一种非常天真的方法是:

SELECT
    *
FROM MyTable t1
WHERE EXISTS
    (
        SELECT 1 FROM MyTable WHERE ACCOUNT = t1.ACCOUNT AND Activity = 'Email'
    )
    AND EXISTS
    (
        SELECT 1 FROM MyTable WHERE ACCOUNT = t1.ACCOUNT AND Activity = 'Appointment'
    )

答案 1 :(得分:0)

假设该表的名称类似于AccountActivity

SELECT * 
FROM AccountActivity 
WHERE Account IN (
    SELECT AccountID 
    FROM AccountActivity 
    WHERE Activity = 'Email')
AND Account IN (
    SELECT AccountID 
    FROM AccountActivity 
    WHERE Activity = 'Appointment')

答案 2 :(得分:0)

这可以通过几种方式完成。想到的第一种方法是使用Exists子句几个关系:

Select  *
From    MyTable t1
Where   Exists  (
                    Select  Null
                    From    MyTable t2
                    Where   t1.Account = t2.Account
                        And t2.Activity = 'Email'
                )
    And Exists  (
                    Select  Null
                    From    MyTable t3
                    Where   t1.Account = t3.Account
                        And t3.Activity = 'Appointment'
                )

sql fiddle

或者有几个自我加入:

Select  t1.*
From    MyTable t1
join    MyTable t2
    on  t1.Account = t2.Account
    and t2.Activity = 'Email'
join    MyTable t3
    on  t1.Account = t3.Account
    and t3.Activity = 'Appointment'

sql fiddle

答案 3 :(得分:0)

这是一种方法。使用使用相关子查询的EXISTS谓词来检查"其他"是否存在。行。这假设您只想返回值为'电子邮件'和“预约'在“活动”列中,并排除具有任何其他活动值的行。 (这不是最有效的方法。)

SELECT t.account
     , t.activity
  FROM example_table t
 WHERE t.activity IN ('Email','Appointment')
   AND EXISTS ( SELECT 1
                  FROM example_table d
                 WHERE d.account = t.account
                   AND d.activity = 
                         CASE t.activity
                           WHEN 'Email' THEN 'Appointment'
                           WHEN 'Appointment' THEN 'Email'
                        END
              )

<强> ADDITION

以上是适用于原始查询的方法(后来作为另一个答案的评论提供......)

SELECT t.ACCOUNT
     , t.COMPANY
     , h.RESPONSE
     , h.DAT_ AS Resp_Date
     , h.USERNAME
     , DATE_FORMAT(p.ENDDATE,'%M') AS Renewal
     , t.OWNER
     , h.CustomerStatus
     , h.Contact
     , a.ANAL14 AS APPDATE 
  FROM TELRCMxxx t
  JOIN TELCOMxxx h
    ON t.ACCOUNT = h.ACCOUNT
   AND h.ACTIVITY in ('Appointment','email')
   AND EXISTS 
       ( SELECT 1
           FROM TELCOMxxx b
          WHERE b.ACCOUNT = h.ACCOUNT
            AND b.ACTIVITY = CASE h.ACTIVITY
                               WHEN 'email' THEN 'Appointment'
                               WHEN 'Appointment' THEN 'email'
                             END
       )
  LEFT
  JOIN ACCSTOxxx p
    ON t.ACCOUNT = p.ACCOUNT
  LEFT
  JOIN RCMANLxxx a
    ON t.ACCOUNT = a.ACCOUNT

注意:原始查询与h的LEFT联接,但&#34;外部&#34; WHERE子句否定了连接操作,它有效地验证了h.ACTIVITY IS NOT NULL。删除了LEFT关键字,并将h.ACTIVITY IN ('Appointment','email')谓词从WHERE子句移动到连接的ON子句。但这并没有改变任何关于查询的内容。

对查询的更改是添加&#34; EXISTS&#34;谓词检查h中是否存在另一行,匹配ACCOUNT,并匹配“约会”&#39;或者&#39;电子邮件&#39;,与被检查的h行中的值相反。

请注意:

            AND b.ACTIVITY = CASE h.ACTIVITY 
                             WHEN 'email' THEN 'Appointment'
                             WHEN 'Appointment' THEN 'email'
                             END

相当于:

            AND ( ( b.ACIVITY = 'email' AND h.ACTIVITY = 'Appointment' )
                 OR
                  ( b.ACIVITY = 'Appointment' AND h.ACTIVITY = 'email' )
                )

END ADDITION


如果需要返回帐户的所有行,包括活动的其他值,则从外部查询的WHERE子句中删除t.Activity IN谓词,并检查是否存在&# 39;电子邮件&#39;和“预约&#39;该帐户的行:

SELECT t.account
     , t.activity
  FROM example_table t
 WHERE EXISTS ( SELECT 1
                  FROM example_table e
                 WHERE e.account = t.account
                   AND e.activity = 'Email'
              )
   AND EXISTS ( SELECT 1
                  FROM example_table a
                 WHERE a.account = t.account
                   AND a.activity = 'Appointment'
              )

这是最有效的方法,但会返回指定的结果。

对于大型集合,(通常)更有效的方法是使用JOIN操作。

要获取具有“电子邮件”和“电子邮件”的不同帐户值的列表。和“预约&#39;行:

SELECT e.account
  FROM example_table e
  JOIN example_table a
    ON a.account = e.account
       AND a.activity = 'Appointment'
 WHERE e.activity = 'Email'
 GROUP BY e.account

从表中获取这些帐户的所有行:

SELECT t.account
     , t.activity
  FROM example_table t
  JOIN ( SELECT e.account
           FROM example_table e
           JOIN example_table a
             ON a.account = e.account
            AND a.activity = 'Appointment'
          WHERE e.activity = 'Email'
         GROUP BY e.account
       ) s
    ON s.account = t.account

如果您只想返回具有特定活动值的行,则可以添加WHERE子句,例如

 WHERE t.activity IN ('Email','Appointment','Foo')

答案 4 :(得分:0)

使用GROUP BYHAVING

的简单而优雅的解决方案
SELECT account, COUNT(DISTINCT(activity)) AS diff_acts
FROM account_activity
WHERE activity IN ('Appointment', 'Email')
GROUP BY account
HAVING diff_acts > 1

<强> SQL Fiddle

如果您想要所有行,请按以下步骤操作

SELECT * 
FROM account_activity
WHERE account IN (
  SELECT account
  FROM account_activity
  WHERE activity IN ('Appointment', 'Email')
  GROUP BY account
  HAVING COUNT(DISTINCT(activity)) > 1 )

<强> SQL Fiddle

答案 5 :(得分:0)

这会有用吗?

select src.account, src.activity
from
(
select account, activity, COUNT(activity) as cnt
from mytable as t1
group by account, activity
) as src 
where cnt = 1
order by src.account

答案 6 :(得分:0)

简单的内部联接将起作用

select account from MyTable as T1
inner join MyTable as T2 on (T2.Account = T1.Account and T2.Activity = 'Appointment')
where T1.Activity = 'EMail'

ADDED

当然,如果性能是一个问题,Activity上的索引会很有用,但无论你如何编写查询,这都是非常有用的

答案 7 :(得分:0)

从x所在的帐户中选择帐户,活动 (从

中选择帐户

(在x.account = x1.account和x.activity&lt;&gt; x1.activity中选择x.account,x1.account as account1 from x join x as x1)summary1

其中summary1.account1不为null )

不知道mysql但是这是在sybase / MS类型db中工作的通用sql。