У меня есть таблица с некоторыми из следующих данных:
+------+--------+-----+------+
| Team | Status | Bye | Wins |
+------+--------+-----+------+
| Cle | New | 1 | 5 |
| Tam | New | 3 | 0 |
| Bal | New | 3 | 2 |
| Ind | Cur | 4 | 0 |
| LAC | New | 4 | 2 |
| NYG | Cur | 5 | 0 |
| Chi | Cur | 5 | 0 |
+------+--------+-----+------+
Существует 5 недель, и запрос может вернуть результат без конкретной недели, скажем, 2 в этой ситуации. Я хочу вернуть набор записей из таблицы, но также вернуть строку (и) с пропущенным номером на неделе до свидания, а все остальное в этой строке пусто (там, где нет пока). Я думаю, что могу сделать это с помощью UNION, но, похоже, много работы и надеюсь, что есть более простой \ более эффективный способ.
Я видел другие сообщения, возвращающие пустую строку, но они не включают в себя возврат других допустимых строк вместе с ним. Спасибо за вашу помощь.
3 ответа
Здесь есть и другие отличные ответы, но я поделюсь тем, что сделал в аналогичной ситуации. По сути, у меня есть таблица «по умолчанию», к которой я могу UNION, а затем только возвращаю из нее недостающие строки.
На основе приведенных выше примеров данных вы создали следующий пример, который вы можете запустить в SSMS.
-- replicate your environment --
DECLARE @data TABLE ( [team] VARCHAR(3), [status] VARCHAR(3), [bye] INT, [wins] INT );
INSERT INTO @data ( [team], [status], [bye], [wins] )
VALUES
( 'Cle', 'New', 1, 5 )
, ( 'Tam', 'New', 3, 0 )
, ( 'Bal', 'New', 3, 2 )
, ( 'Ind', 'Cur', 4, 0 )
, ( 'LAC', 'New', 4, 2 )
, ( 'NYG', 'Cur', 5, 0 )
, ( 'Chi', 'Cur', 5, 0 );
-- declare a "defaults" table variable --
DECLARE @defaults TABLE ( [team] VARCHAR(2) DEFAULT '--', [status] VARCHAR(2) DEFAULT '--', [bye] INT, [wins] INT );
-- insert default data based on what I surmised from your question --
INSERT INTO @defaults ( [bye], [wins] ) VALUES ( 1, 0 ), ( 2, 0 ), ( 3, 0 ), ( 4, 0 ), ( 5, 0 );
-- select data using the "defaults" table to "fill in the wholes" --
SELECT [team], [status], [bye], [wins] FROM @data
UNION
SELECT [team], [status], [bye], [wins] FROM @defaults
WHERE [bye] NOT IN ( SELECT [bye] FROM @data )
ORDER BY
[bye], [team];
Что возвращается
+------+--------+-----+------+
| team | status | bye | wins |
+------+--------+-----+------+
| Cle | New | 1 | 5 |
| -- | -- | 2 | 0 |
| Bal | New | 3 | 2 |
| Tam | New | 3 | 0 |
| Ind | Cur | 4 | 0 |
| LAC | New | 4 | 2 |
| Chi | Cur | 5 | 0 |
| NYG | Cur | 5 | 0 |
+------+--------+-----+------+
Другой альтернативой было бы расширить использование @ {Y0gesh} FROM ( VALUES )
в @ Yogesh:
SELECT [team], [status], [bye], [wins] FROM @data
UNION
SELECT [team], [status], [bye], [wins]
FROM (
VALUES ( '--', '--', 1, 0 ), ( '--', '--', 2, 0 ), ( '--', '--', 3, 0 ), ( '--', '--', 4, 0 ), ( '--', '--', 5, 0 )
) AS MyTable( [team], [status], [bye], [wins] )
WHERE [bye] NOT IN ( SELECT [bye] FROM @data )
ORDER BY
[bye], [team];
Который возвращает те же результаты, что и выше, без необходимости / издержек табличной переменной.
Вы можете использовать конструкцию values
с join
:
select t.bye, tt.*
from ( values (2)
) t (bye) left join
table tt
on t.bye = tt.bye;
РЕДАКТИРОВАТЬ: После повторного рассмотрения вопроса вы, кажется, хотите union
с not exists
:
select t.team, t.status, t.bye, t.wins
from table t
where bye = 2
union all
select t.team, t.status, t.bye, t.wins
from table t
where not exists (select 1 from table where bye = 2);
РЕДАКТИРОВАТЬ: используйте рекурсивный cte
, чтобы найти отсутствующие bye
:
with t as (
select min(bye) mn_bye, max(bye) mx_bye
from table
union all
select mn_bye + 1, mx_bye
from t
where mn_bye < mx_bye
)
select tt.*, coalesce(cast(t.mn_bye as varchar(255)), 'missing')
from t left join
table tt
on tt.bye = t.mn_bye;
Я специально удалил Bye
с 4, чтобы результат был лучше виден.
declare @t table
(
Team char(3) null,
[Status] char(3) null,
Bye tinyint null,
Wins tinyint null
);
insert into @t values
('Cle', 'New', 1, 5),
('Tam', 'New', 3, 0),
('Bal', 'New', 3, 2),
--('Ind', 'Cur', 4, 0),
--('LAC', 'New', 4, 2),
('NYG', 'Cur', 5, 0),
('Chi', 'Cur', 5, 0);
with info as
(
select x.*, x.next_row_bye - Bye diff
from
(
select *,
LEAD(Bye) OVER (ORDER BY Bye) next_row_bye,
Bye + 1 next_bye
from @t
) x
)
select null Team, null [Status], next_bye Bye, 0 Wins
from info
where diff > 0
union
select *
from @t
order by Bye;
РЕЗУЛЬТАТ:
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.