通过id在一列中从多行获取单个记录

时间:2014-01-24 13:58:16

标签: sql sql-server database resultset

我正在尝试从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

提前致谢

4 个答案:

答案 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条件集可以表示为表变量或表值参数 - 这有助于保持这种方法的可维护性(特别是count = x变化)。 Another Fiddle

答案 1 :(得分: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

答案 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

答案 3 :(得分:0)

如果您总是需要两个活动的交集,您可以执行以下操作。我将它包装在一个表函数中,该函数将2个活动ID作为输入变量。

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