SQL Server:如果存在值,则从多行中进行SELECT

时间:2011-12-08 07:52:24

标签: sql sql-server sql-server-2008

我正在尝试编写一个查询,根据是否有更新的值从多行中选择数据。这已经让我头疼很久了。该表的结构如下:

UniqID ProblemID  DateTime   Status PersonID ResponsibleID ActionID Comment  Deadline    PartID
15589   15589    01/16 12:11   0       25         48          12      bla1   01/16 12:11  T9865
15592   15589    01/16 12:25   1       48         48          105     bla2   null         null
15601   15589    01/16 13:08   3       56         null        195     bla3   null         N2654
15641   15589    01/17 18:02   3       11         23          35      null   01/18 15:00  null
15705   15589    01/18 10:24   5       23         null        255     bla4   null         null

这是一个错误的日志,我需要对这些数据执行几个稍微不同的查询。

  • e.g。如果第48个人涉及此错误(15589)PersonIDResponsibleID

此查询必须返回

    ProblemID (first)DateTime (last)Status (first)Person (last)Responsible (last)action (first)Comment (last)deadline (last)PartID        
      15589      01/16 12:11       5            25            23                255         bla1        01/18 15:00      N2654
  • 例如显示过去24小时的所有错误
  • 例如显示涉及PartID T9865的所有错误

我已经对此查询进行了多次尝试,但最好的结果是查询从最后一行或第一行中选择所有内容。我实际上正在努力弄清楚如果最后一行中没有包含(最后一个)ResponsibleID的话。显然,对于其他列也是如此。我现在能想到的唯一解决方案是一个简单的选择,它将返回所有行,并使用PHP在foreach循环中过滤必要的数据。因为在多行中选择不同的值超出了我的技能:)

提前致谢

3 个答案:

答案 0 :(得分:2)

我能想到的唯一解决方案是重复子选择中的条件。我认为没有其他方法可以获得NOT NULL的第一个/最后一个列值。

SQL语句

;WITH CurrentProblemID AS (
  SELECT  DISTINCT ProblemID
  FROM    Mistakes 
  WHERE   PersonID = 48 
          OR ResponsibleID = 48
)

SELECT  [ProblemID] = cpi.ProblemID
        , [(first) DateTime] = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND DateTime IS NOT NULL)
        , [(last) Status] = (SELECT Status FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Status IS NOT NULL))
        , [(first) Person] = (SELECT PersonID FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PersonID IS NOT NULL))
        , [(last) Responsible] = (SELECT ResponsibleID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ResponsibleID IS NOT NULL))
        , [(last) Action] = (SELECT ActionID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ActionID IS NOT NULL))
        , [(first) Comment] = (SELECT Comment FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Comment IS NOT NULL))
        , [(last) Deadline] = (SELECT Deadline FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Deadline IS NOT NULL))
        , [(last) PartID] = (SELECT PartID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PartID IS NOT NULL))
FROM    CurrentProblemID cpi

测试脚本

;WITH Mistakes AS (
  SELECT  *
  FROM    ( 
            VALUES
              (15589, 15589, '01/16 12:11', 0, 25, 48, 12, 'bla1', '01/16 12:11', 'T9865')
              , (15592, 15589, '01/16 12:25', 1, 48, 48, 105, 'bla2', null, null)
              , (15601, 15589, '01/16 13:08', 3, 56, null, 195, 'bla3', null, 'N2654')
              , (15641, 15589, '01/17 18:02', 3, 11, 23, 35, null, '01/18 15:00', null)
              , (15705, 15589, '01/18 10:24', 5, 23, null, 255, 'bla4', null, null)
          ) AS v (UniqID, ProblemID, DateTime, Status, PersonID, ResponsibleID, ActionID, Comment, Deadline, PartID)
)          
, CurrentProblemID AS (
  SELECT  DISTINCT ProblemID
  FROM    Mistakes 
  WHERE   PersonID = 48 
          OR ResponsibleID = 48
)

SELECT  [ProblemID] = cpi.ProblemID
        , [(first) DateTime] = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND DateTime IS NOT NULL)
        , [(last) Status] = (SELECT Status FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Status IS NOT NULL))
        , [(first) Person] = (SELECT PersonID FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PersonID IS NOT NULL))
        , [(last) Responsible] = (SELECT ResponsibleID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ResponsibleID IS NOT NULL))
        , [(last) Action] = (SELECT ActionID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ActionID IS NOT NULL))
        , [(first) Comment] = (SELECT Comment FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Comment IS NOT NULL))
        , [(last) Deadline] = (SELECT Deadline FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Deadline IS NOT NULL))
        , [(last) PartID] = (SELECT PartID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PartID IS NOT NULL))
FROM    CurrentProblemID cpi

答案 1 :(得分:1)

TBH这可能不是SQL要解决的问题,而是业务逻辑代码的问题。因此,虽然您无疑会提出一个可以满足您需求的查询,但是将所有记录返回给客户端应用程序并让客户端代码处理确定要显示的相关记录的问题可能更简单。

答案 2 :(得分:0)

以下代码可能会为您提供解决方案

SELECT  ABC.PROBLEMID,
        ABC.DATETIME,--(first)DateTime 
        ABC.STATUS,--(last)Status
        ABC.PERSON,-- (first)Person
        ABC.RESPONSIBLE,-- (last)Responsible
        ABC.ACTION,-- (last)action
        ABC.COMMENT,-- (first)Comment
        ABC.DEADLINE,-- (last)deadline
        ABC.PARTID -- (last)PartID
(
SELECT TOP 1 PROBLEMID,DATETIME,PERSON,COMMENT 
FROM YOURTABLE
ORDER BY DATETIME ASC
OR
SELECT TOP 1 STATUS,RESPONSIBLE,ACTION,DEADLINE,PARTID
FROM YOURTABLE
ORDER BY DATETIME DESC
) ABC
WHERE ABC.PROBLEMID IN (SELECT  DISTINCT ProblemID
                        FROM    Mistakes 
                        WHERE   PersonID = 48 
                           OR   ResponsibleID = 48)