Можно ли «объединить» две строки в наборе результатов запроса SQL Server? - PullRequest
0 голосов
/ 28 июня 2011

Я смотрю на запрос, который выводит что-то вроде следующего:

Group | Date 1     | Value 1 | Date 2      | Value 2
------+------------+---------+-------------+--------
    A | 2011-06-15 | 105     | NULL        | NULL
    A | NULL       | NULL    | 2011-06-16  | 107
    B | 2011-06-18 | 567     | NULL        | NULL
    B | NULL       | NULL    | 2011-06-20  | 525

То, что я хочу, это "сгладить" эти результаты по группам - вроде как COALESCE по строке:

Group | Date 1     | Value 1 | Date 2      | Value 2
------+------------+---------+-------------+--------
    A | 2011-06-15 | 105     | 2011-06-16  | 107
    B | 2011-06-18 | 567     | 2011-06-20  | 525

Обратите внимание, что в каждой группе будет только 2 строки; это не относится к произвольному количеству точек данных, это, по сути, запрос «до и после».

Возможно ли это сделать за одиночный проход? (В результатах содержится большое количество данных). Это значит:

  • Нет временные таблицы, табличные переменные или аналогичные промежуточные шаги (CTE в порядке);
  • Нет присоединения к себе, то есть очевидное решение получения MIN и MAX в одном запросе, а затем присоединение к этим датам для получения значений. Как упоминалось выше, это результирующий набор дорогого запроса, и я очень стараюсь не удваивать нагрузку.

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

P.S. Обратите внимание, что для группы «B» значение 2 ниже значения 1. Я сделал это явно, чтобы продемонстрировать, почему один GROUP BY, который принимает MIN и MAX как даты, так и значения, не собирается для получения ожидаемых результатов. Значения должны быть соотнесены с датами.

Ответы [ 2 ]

0 голосов
/ 28 июня 2011

Не уверен, что это то, что вы хотите.Если у вас только две строки на группу, вы можете попробовать это.

;WITH cte as
(
    -- You sql output here
    SELECT  *
    FROM    table
)
SELECT  a1.group,a1.date1,a1.value1,a2.date2,a2.value2
FROM    cte a1
INNER JOIN cte a2
 ON a2.date2 IS NOT NULL
 AND a1.group = a2.group
WHERE a1.date1 IS NOT NULL
0 голосов
/ 28 июня 2011

Предполагая, что вы всегда получаете пары в Group s, вы можете сделать GROUP BY [Group] и для каждого из 4 столбцов выбрать MAX() (который в основном будет принимать ненулевое значение).

Редактировать: , если у вас есть набор данных со столбцами «Группа», «Дата» и «Значение» и вы хотите объединить их, чтобы у вас были «Группа», «Дата 1», « Используйте столбцы «Значение 1», «Дата 2» и «Значение 2», используйте это (первый CTE представляет данные теста):

WITH Results AS (
    SELECT 'A' [Group], CONVERT(datetime, '2011-06-15') [Date], 105 [Value]
    UNION ALL
    SELECT 'A' [Group], CONVERT(datetime, '2011-06-16') [Date], 107 [Value]
    UNION ALL
    SELECT 'B' [Group], CONVERT(datetime, '2011-06-18') [Date], 567 [Value]
    UNION ALL
    SELECT 'B' [Group], CONVERT(datetime, '2011-06-20') [Date], 525 [Value]
),
ResultsIndexed AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY r.[Group] ORDER BY r.[Date]) ix, r.* FROM Results r
)
SELECT r1.[Group], r1.[Date] [Date 1], r1.[Value] [Value 1], r2.[Date] [Date 1], r2.[Value] [Value 1]
    FROM ResultsIndexed r1
    JOIN ResultsIndexed r2 ON (r1.[Group] = r2.[Group]) AND (r2.[ix] = 2)
    WHERE r1.[ix] = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...