Как сохранить порядок значений столбцов в объединении? - PullRequest
0 голосов
/ 03 июля 2018

Я делаю массовую вставку в таблицу, используя SELECT и UNION. Мне нужно, чтобы порядок значений SELECT был неизменным при вызове INSERT, но похоже, что значения вставляются в порядке возрастания, а не в указанном порядке.

Например, приведенный ниже оператор вставки

declare @QuestionOptionMapping table
(
    [ID] [int] IDENTITY(1,1)
  , [QuestionOptionID] int
  , [RateCode] varchar(50)
)

insert into @QuestionOptionMapping (
    RateCode
)
select
   'PD0116'
union
select
  'PL0090'
union
select
  'PL0091'
union
select
  'DD0026'
union
select
  'DD0025'

SELECT * FROM @QuestionOptionMapping

отображает данные как

(5 row(s) affected)
ID          QuestionOptionID RateCode
----------- ---------------- --------------------------------------------------
1           NULL             DD0025
2           NULL             DD0026
3           NULL             PD0116
4           NULL             PL0090
5           NULL             PL0091

(5 row(s) affected)

Как выборка вставленных данных может возвращать тот же порядок, что и при вставке?

Ответы [ 4 ]

0 голосов
/ 03 июля 2018

Таблицы SQL представляют неупорядоченные множества. Однако столбец identity на insert будет следовать порядку order by.

Ваши данные вышли из строя из-за удаления дубликата в union. Однако я бы предложил написать запрос для явной сортировки данных:

insert into @QuestionOptionMapping (RateCode)
    select ratecode
    from (values (1, 'PD0116'), 
                 (2, 'PL0090'),
                 (3, 'PL0091'),
                 (4, 'DD0026'),
                 (5, 'DD0025')
         ) v(ord, ratecode)
    order by ord;

Тогда обязательно используйте order by для выбора:

select qom.*
from @QuestionOptionMapping qom
order by id;

Обратите внимание, что здесь также используется табличный конструктор values(), который является очень удобным синтаксисом.

0 голосов
/ 03 июля 2018

Если вы не выбираете из таблиц?
Затем вы можете вставить VALUES вместо выбора с объединениями.

insert into @QuestionOptionMapping (RateCode) values
 ('PD0116')
,('PL0090')
,('PL0091')
,('DD0026')
,('DD0025')

Или в вашем запросе измените все UNION на UNION ALL.

Разница между UNION и UNION ALL заключается в том, что UNION удаляет повторяющиеся строки. В то время как UNION ALL просто склеивает наборы результатов из выборок вместе.
И чтобы UNION мог найти эти дубликаты, сначала он должен отсортировать их.
Но UNION ALL не заботится об уникальности, поэтому его не нужно сортировать.

3-й вариант - просто заменить один оператор вставки на несколько операторов вставки. Одна вставка на значение. Таким образом, полностью избегая UNION.
Но этот метод антигольфокодирования также самый многословный.

0 голосов
/ 03 июля 2018

Ваша проблема в том, что вы помещаете их не в том порядке, в каком думаете. UNION - это только отдельные значения, и он, как правило, сортирует значения для облегчения различных значений. Запустите оператор select в одиночку, и вы увидите.

Если вставить с помощью values, то порядок сохраняется:

insert into @QuestionOptionMapping (RateCode) values
('PD0116'), ('PL0090'), ('PL0091'), ('DD0026'), ('DD0025')

select * from @QuestionOptionMapping order by ID
0 голосов
/ 03 июля 2018

SQL Server хранит ваши строки как неупорядоченный набор. Точки данных могут быть или не быть смежными, и они могут или не могут быть в «порядке», данные были указаны в ваших операторах вставки.

Когда вы запрашиваете данные, механизм извлекает строки в наиболее эффективном порядке, как определено оптимизатором. Нет никаких гарантий, что порядок будет одинаковым при каждом запросе данных.

Единственный способ гарантировать порядок набора результатов - включить явное предложение ORDER BY в инструкцию SELECT.

См. Этот ответ для более глубокого обсуждения того, почему это так. Порядок строк по умолчанию в запросе SELECT - SQL Server 2008 против SQL 2012

Используя опцию SELECT / UNION для оператора INSERT, вы создаете неупорядоченный набор, который SQL Server принимает как набор, а не как последовательность входных данных. Разделите вставки на отдельные операторы, если вам нужно, чтобы значения IDENTITY применялись по порядку. Еще лучше, если нумерация строк имеет значение, не оставляйте это на волю случая. Явно пронумеруйте строки на вставке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...