2014-06-17 3 views
3

Моя таблица определена следующим образом:Как написать SQL-запрос для следующей таблицы?

Название - это строка и свойство тоже.

ID | Name | Property 

Пример для данных в этой таблице это:

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

Теперь я хотел бы запросить все люди, которые имеют бюллетень собственности и регистрации. В результате я должен получить Петра, потому что у него есть и собственность.

Так результирующая таблица должна быть как:

ID | Name | Property 
1 Peter Newsletter 
3 Peter Register 

Так что все я пытаюсь запроса, который человек имеет как бюллетень свойства, и зарегистрироваться.

ответ

5

Вот один метод:

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' 
      ); 

Если вы хотите просто список имен, возможно, с id с, я хотел бы сделать, что, как:

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

Как вы получите список id s зависит от вашей базы данных, что-то вроде listagg() или group_concat() или string_agg().

2

Альтернативой, в значительной степени по той же схеме, как решение Гордона, но без использования EXISTS:

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

Я попробую оба ваших подхода, теперь я застрял в чем-то другом. Дайте мне немного времени, и я вознагражу наилучший рабочий подход, приняв его как решение =) Спасибо до сих пор – PreDer

1

Это трудно быть уверенным, не зная больше о данных. Учитывая точные требования, которые вы дали нам, это даст результаты, которые вы показали:

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 

Но незначительные различия в ваших требованиях будут натворить. Например, будет ли когда-либо быть Значения свойств, отличные от указанных вами двух? Или имя может появляться несколько раз с тем же свойством?

EDIT: добавленное предложение WHERE ограничивает строки в CTE запрошенным конкретным набором значений Property. Это из более подробных требований в комментариях.

+0

Есть больше собственности, чем два, которые я перечислил, но эти два являются интересными для меня.Имя не может отображаться несколько раз с тем же свойством. – PreDer

+0

Ваш комментарий сужает возможности, поэтому предложение WHERE теперь ограничивает строки в CTE (Common Table Expression, т. Е. Предложение WITH WITH). Использование CTE - это альтернативный синтаксис, который стоит изучать. Предикат 'IN()' может быть _sub-select_ вместо явного списка, так что желаемый список 'Property' может быть из временной таблицы. – user2338816

1

Еще один способ:

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

1

Еще один, для записи

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) 

Это потребует только две sacns через стол.

Смежные вопросы