SQL Server: ВЫБРАТЬ из нескольких строк, если существуют значения - PullRequest
2 голосов
/ 08 декабря 2011

Я пытаюсь написать запрос, который бы выбирал данные из нескольких строк в зависимости от того, есть ли более новое значение. Это давало мне головную боль уже давно. Таблица структурирована следующим образом:

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

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

  • например. если человек 48 был связан с этой ошибкой (15589) как PersonID или как ResponsibleID.

Этот запрос должен был бы вернуть

    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, если он не содержится в последней строке. То же самое для других столбцов, очевидно. Единственное решение, о котором я могу думать прямо сейчас, - это простой выбор, который вернул бы мне все строки и просто отфильтровал эти необходимые данные в цикле foreach с PHP. Потому что выбор разных значений в нескольких строках просто не в моей компетенции:)

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

Ответы [ 3 ]

2 голосов
/ 08 декабря 2011

Единственное решение, которое я могу придумать, - это повторить условия в подпунктах. Я не вижу другого способа добраться до значений первого / последнего столбца, которые 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 голос
/ 08 декабря 2011

TBH это, вероятно, не проблема для решения SQL, а проблема для кода бизнес-логики. Поэтому, хотя вы, несомненно, получите запрос, который будет делать то, что вам нужно, может быть проще просто вернуть все записи клиентскому приложению, и клиентский код решает проблему определения соответствующих записей для отображения.

0 голосов
/ 08 декабря 2011

Следующий код может дать вам решение

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...