使用PATINDEX时选择DISTINCT字段

时间:2013-08-22 23:17:57

标签: sql sql-server-2008 tsql

我有一个名为Issues的表,我需要从中获取数据。我正在使用另一个名为IssueActivities的表加入“问题”表。因此,对于IssueID的每个实例,可能存在1到多个IssueActivities。在IssueActivities表中有一个名为Notes的字段,其数据类型为text。我正在尝试选择一个DISTINCT的IssueID列表,其中Notes字段不包含2个特定的字符串。

这是我的SQL:

SELECT DISTINCT i.IssueID
FROM Issues i
INNER JOIN IssueActivities ia ON i.IssueID = ia.IssueID
WHERE i.IssueStatusID = 2 --Closed issues only
AND (PATINDEX('%Pending DR%', ia.Notes) < 1 AND PATINDEX('%Pending E%', ia.Notes) < 1)

这个sql的问题在于,它返回具有该条件的问题的IssueID,因为Issue可以有很多 IssueActivities,因此并非所有行都包含该条件。那有意义吗?这是一个简单的例子:

问题表

IssueID | IssueStatusID
-----------------------
1700       2
1701       2

IssueActivities表

IssueActivityID | IssueID | Notes
---------------------------------
1                 1700      Issue Entered
2                 1700      Sub Status changed from New to In Progress
3                 1700      Sub Status changed from In Progress to Pending DR
4                 1701      Issue Entered
5                 1701      Issue Assigned
6                 1701      Sub Status changed from New to Closed

因此,从上表中,我只想得到问题1701,因为属于它的所有IssueActivities,它们都没有包含我正在使用的标准。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:0)

如果我理解正确,您需要先选择您要忽略的内容:

SELECT DISTINCT IssueID
FROM IssuesActivities
WHERE PATINDEX('%Pending DR%', ia.Notes) > 0 OR PATINDEX('%Pending E%', ia.Notes) > 0

然后你可以忽略它:

SELECT DISTINCT i.IssueID
FROM Issues i
LEFT JOIN (SELECT DISTINCT IssueID
           FROM IssuesActivities
           WHERE PATINDEX('%Pending DR%', ia.Notes) > 0 OR PATINDEX('%Pending E%', ia.Notes) > 0
          )ia
  ON i.IssueID = ia.IssueID
WHERE i.IssueStatusID = 2 --Closed issues only
   AND ia.IssueID IS NULL

答案 1 :(得分:0)

您应该找到要排除的行,然后在where子句中删除它们。此示例使用APPLY查找每个“问题”行中包含“待定DR”或“待定E”的任何IssueActivity行。这是SQLFiddle

SELECT i.IssueID
FROM Issues i
OUTER APPLY(
  SELECT TOP 1 ia.IssueActivityID
  FROM IssueActivities ia
  WHERE ia.IssueID = i.IssueID
    AND (PATINDEX('%Pending DR%', ia.Notes) > 0
      OR PATINDEX('%Pending E%', ia.Notes) > 0)
) pending
WHERE i.IssueStatusID = 2
  AND pending.IssueActivityID IS NULL

答案 2 :(得分:0)

您需要将对IssueActivities的引用替换为仅返回该要包含的表中的记录的子查询,将连接更改为外连接,以便从Issues返回所有记录,并将标准更改为仅在Issues查询具有匹配记录的位置返回IssueActivity条记录。

SELECT DISTINCT i.IssueID
FROM Issues AS i LEFT OUTER JOIN
      (SELECT * FROM IssueActivities WHERE (PATINDEX('%Pending DR%', ia.Notes) < 1)
       AND (PATINDEX('%Pending E%', ia.Notes) < 1)) AS ia ON i.IssueID = ia.IssueID
WHERE (i.IssueStatusID = 2) AND ia.IssueID IS NULL

你也可以使用:

SELECT i.IssueID
FROM Issues AS i
WHERE (i.IssueStatusID = 2) AND NOT EXISTS (SELECT * FROM IssueActivities AS ia 
WHERE (PATINDEX('%Pending DR%', ia.Notes) < 1) AND (PATINDEX('%Pending E%', ia.Notes) < 1)
      AND (i.IssueID = ia.IssueID)) )