оператор sql с группировкой по
Вопрос
после очень длинного sql-запроса результат имеет следующую форму:
col1 | col2 | col3 | col4
------+------+------+-----
1234 | 1 | aaaa | bbbb
2378 | 0 | aaaa | bbbb
9753 | 1 | cccc | uuuu
1234 | 0 | iiii | yyyy
2378 | 1 | iiii | yyyy
9753 | 1 | tttt | mmmm
но мне это не нужно в таком виде.мне нужно сделать еще один sql-оператор для этого результата, где мне нужно использовать группа по третий и четвертый столбец.другими словами, две строки в одной, вот так:
col1 | col2 | col3 | col4 | col5 | col6
-----+------+------+------+------+-----
1234 | 1 | 2378 | 0 | aaaa | bbbb
1234 | 1 | 2378 | 0 | aaaa | bbbb
9753 | 1 | null | null | cccc | uuuu
1234 | 0 | 2378 | 1 | iiii | yyyy
9753 | 1 | null | null | tttt | mmmm
Решение
Вы можете решить эту проблему, создав две дополнительные таблицы (временные или нет, зависит от ваших требований и механизма SQL), структура которых будет отображать столбцы из запроса.
Например:
CREATE TABLE TableA (
Col1 int,
Col2 bit,
Col3 varchar(4),
Col4 varchar(4)
)
CREATE TABLE TableB (
Col1 int,
Col2 bit,
Col3 varchar(4),
Col4 varchar(4)
)
Обратите внимание, что это всего лишь пример структуры, основанной на представленных вами выходных данных.
После создания этих двух таблиц вам придется вставить данные из запроса в каждую из таблиц.
Добавлен:Вам не нужно выполнять один и тот же запрос дважды. Выполните его один раз, поместите данные в Таблицу A, затем выполните SELECT в Таблице A и поместите данные в Таблицу B.Это сэкономит вам много времени.
Последним шагом будет выполнение запроса к таблицам TableA и TableB с помощью JOIN для их столбцов Col3 и Col4.Что-то вроде этого:
SELECT A.Col1, A.Col2, B.Col1, B.Col2, COALESCE(A.Col3, B.Col3), COALESCE(A.Col4, B.Col4)
FROM TableA A INNER JOIN TableB B ON A.Col3 = B.Col3 AND A.Col4 = B.Col4
Надеюсь, это поможет.
Также имейте в виду, что у этого решения есть один существенный недостаток:
Если вы измените количество столбцов или их тип данных в исходном запросе, вам также придется обновить определения таблиц.Возможным решением этой проблемы может быть использование динамического SQL, но обычно это не рекомендуется.
После редактирования (вы указали дополнительные NULLS в выходных данных):
Если вы хотите сохранить значения NULL, вам следует использовать другое соединение, например: LEFT OUTER JOIN
Другие возможные решения:
Просто замените (SELECT * FROM dbo.Test) своим длинным запросом.Однако это приведет к тому, что запрос будет выполнен дважды.
ВЫБЕРИТЕ.*, Б.* FROM (SELECT * FROM dbo.Test) A ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ (SELECT * FROM dbo.Test) B ON A.Col3 = B.Col3 И A.Col4 = B.Col4 И A.Col1 <> B.Col1 AND A .Col2 <> B.Col2
Если вы используете SQL 2005, вы можете попробовать использовать оператор CROSS APPLY.
Могут быть и другие решения, но вам необходимо более подробно описать используемый вами механизм SQL и ваши права на базу данных.
Другие советы
Хм,
Я бы бросил результат во временную таблицу.Тогда делай
select
a.col1,
a.col2,
b.col1,
b.col2,
coalesce(a.col3, b.col3) as col5,
coalesce(a.col4,b.col4) as col6
from #tmp a
outer join #tmp b
on a.col3 = b.col3 and a.col4 = b.col4
where a.col2 = 0 and b.col2 = 1
Это, конечно, предполагает, что столбец 2 является индикатором того, какая часть пары у вас есть.
я нашел правильное решение, основанное на первом решении @Wodzu .
во-первых, создайте временное представление, которое будет содержать результат.
с tmp as ( - мое очень длинное заявление sql ... ) Р>
во-вторых, сделайте выбор, так как их два, таким образом, запрос вызывается только один раз.
выберите a. **, b. ** из tmp внутреннего соединения tmp b по условиям.
Спасибо Wodzu