简体   繁体   中英

How to write a SQL-Query for the following table?

My table is defined like this:

Name is a string and property too.

ID | Name | Property

An example for data in this table is this:

ID | Name | Property
1    Peter  Newsletter
2    Paul   Register
3    Peter  Register
4    Shaun  Newsletter
5    Steve  Register

Now I like to query all people that have the property newsletter and register. As a result I should get Peter, because he has both property's.

So the resulting table should be like:

ID | Name | Property
1    Peter  Newsletter
3    Peter  Register

So everything I try to query is which person has both property's newsletter and register.

Here is one method:

select t.*
from table t
where exists (select 1
              from table t2
              where t2.name = t.name and t2.property = 'NewsLetter'
             ) and
      exists (select 1
              from table t2
              where t2.name = t.name and t2.property = 'Register'
             );

If you just want the list of names, perhaps with id s, I would do that as:

select t.name
from table t
where t2.property in ('NewsLetter', 'Register')
group by t.name
having count(distinct property) = 2;

How you get the list of id s depends on your database, something like listagg() or group_concat() or string_agg() .

An alternative, pretty much on the same lines as Gordon's solution, but without using EXISTS :

select * from tablename
where name in (select name from tablename where property = 'Newsletter')
and name in (select name from tablename where property = 'Register')

It's hard to be sure without knowing more about the data. Given the exact requirements that you gave to us, this will give the results you showed:

WITH multprop (multName) AS (
   SELECT NAME FROM myTable
       WHERE Property IN('Newsletter','Register')
       GROUP BY NAME
       HAVING count(*)>1 )
select id, Name, Property
 from multprop inner join myTable
      on multName = Name

But minor differences in your requirements will mess things up. For example, will there ever be Property values other than the two you listed? Or can a Name show up multiple times with the same Property?

EDIT: The added WHERE clause limits rows in the CTE to the requested specific set of Property values. This is from the more detailed requirements in comments.

One more way:

SELECT * FROM T as T1
WHERE Property IN ('Newsletter','Register')
      AND EXISTS (SELECT * FROM T 
                      WHERE Name=T1.Name 
                            and Property IN ('Newsletter','Register')
                            and Property <> T1.Property
                 )

SQLFiddle demo

Another one, for the record

WITH cteHasBoth
 as (select Name
       from MyTable
       where Property in ('Newsletter', 'Register')
       group by Name
       having count(*) = 2)
 select ID, Name
  from MyTable
  where name in (select Name from cteHasBoth)

This would require only two sacns through the table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM