2014-01-24 1 views
2

Я пытаюсь получить некоторые записи из запроса в SQL Server 2008.Получение отдельных записей из нескольких строк по идентификатору в одном столбце

Пути таблица магазин, как это

P_Id  Activity_Id 
----------------------- 
1234  53 
1234  510 
4567  65 
4567  510 
3456  53 
3456  540 
5678  53 
5678  510 

Теперь то, что мне нужно, чтобы получить в котором p_id забронированы активность 53 & 510 или 65 510 &

Если я что-то вроде этого, он не дает мне никаких записей

SELECT P_Id FROM ActivitiesPerPerson WHERE Activity_Id = 53 AND Activity_Id = 510 

Если я сделаю это

SELECT P_Id FROM ActivitiesPerPerson WHERE Activity_Id IN (53, 65, 510) 

Это дает мне некоторые результаты, но это дает мне люди, что заказанные деятельность 53 только вместе с остальными.

Мне нужно получить идентификатор человека, который забронировал 53 & 510 вместе и идентификатор человека, который забронировал 65 & 510 вместе. Все по одному и тому же результату, если это возможно.

У меня есть SQL скрипку с этим http://sqlfiddle.com/#!3/b4c11/2

Заранее спасибо

ответ

1

Вы бы сканировать таблицу один раз и группу по p_id. Сделав это, вам понадобится агрегат, чтобы сообщить вам, что для этого P_Id есть Activity_Id x. Вы можете просто суммировать с аргументом case для этого.Затем возьмите только те p_id, соответствующие Вашим критериям:

SELECT P_Id 
FROM ActivitiesPerPerson 
WHERE Activity_Id IN (53, 65, 510) 
GROUP BY p_Id 
HAVING 
(
    SUM(CASE WHEN Activity_Id = 53 THEN 1 ELSE 0 END) > 0 
    AND 
    SUM(CASE WHEN Activity_Id = 510 THEN 1 ELSE 0 END) > 0 
) 
OR 
(
    SUM(CASE WHEN Activity_Id = 65 THEN 1 ELSE 0 END) > 0 
    AND 
    SUM(CASE WHEN Activity_Id = 510 THEN 1 ELSE 0 END) > 0 
); 

См http://sqlfiddle.com/#!3/b4c11/38.

+0

Просто примечание: предложение WHERE на самом деле не требуется, но может улучшить производительность. Другое примечание. Ваш пример (53 И 510) ИЛИ (65 И 510) можно, конечно, упростить до 510 И (53 ИЛИ 65). –

+0

Спасибо! Это именно то, что я искал! –

2

Устный ваш вопрос, как «найти всех людей, которые сделали все действия в данном наборе», вы можете сделать так, как :

SELECT P_Id, COUNT(*) 
    FROM ActivitiesPerPerson 
    WHERE Activity_Id IN (50, 510, 800) 
    GROUP BY P_Id 
    HAVING COUNT(*) = 3; 

(с учетом данных скрипки, и это предполагает, что ActivitiesPerPerson является уникальным для каждого (PersonId, ActivityID) пары - то есть, что тот же человек не может сделать ту же самую деятельность более-я один раз. Вам также необходимо настроить count = x каждый раз, когда вы меняете количество критериев.

Если вам необходимо исключить возможность дубликатов одного и ту же (person, activity) комбинации давая ложные срабатывания, различны их, как так:

SELECT P_Id, COUNT(*) 
FROM 
(
    SELECT DISTINCT P_Id, Activity_ID 
    FROM ActivitiesPerPerson 
    WHERE Activity_Id IN (50, 510, 800) 
) X 
GROUP BY P_Id 
HAVING COUNT(*) = 3; 

Activities критерии набор может быть выражен в виде переменной таблицы или таблицу значного параметра - это помогает с поддержанием этого подхода (в частности, с изменением числа = х). Another Fiddle

+0

Я предпочитаю ваш ответ на мой! – Bobby

+0

Это правильный способ сделать то, что просит анкета. kudos. – eddiecubed

+1

Я думаю, вы неправильно поняли вопрос. Однако проблема дубликатов в первом запросе будет легче решена с помощью HAVING COUNT (DISTINCT Activity_Id) = 3; –

1

Это немного ужасно, но работает. Числа, взятые из вашей скрипки.

SELECT * 
FROM 
    (SELECT P_Id 
    FROM ActivitiesPerPerson 
    WHERE Activity_Id = 510) AS x INNER JOIN 
    (SELECT P_Id 
    FROM ActivitiesPerPerson 
    WHERE Activity_Id = 50) AS y ON x.P_Id = y.P_Id INNER JOIN 
    (SELECT P_Id 
    FROM ActivitiesPerPerson 
    WHERE Activity_Id = 800) AS z ON x.P_Id = z.P_Id 
0

Если вам всегда нужно пересечение всего 2 видов деятельности, вы можете сделать что-то вроде следующего. Я бы обернул его в функцию таблицы, которая принимает 2 идентификатора activitiy в качестве входных переменных.

Declare @Act1 Int 
Declare @Act2 Int 

Set @Act1 = 50 
Set @Act2 = 510 

SELECT A1.P_Id 
FROM 
     ActivitiesPerPerson A1 
INNER JOIN 
     ActivitiesPerPerson A2 
ON  A1.P_Id = A2.P_Id 
WHERE A1.Activity_Id = @Act1 
AND A2.Activity_Id = @Act2 

SQL Fiddle here

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

  • Нет связанных вопросов^_^