Цикл в программе SQL-сервера с таблицей

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

Исходная таблица: (у меня есть алфавиты в столбце HeadNo)

HeadNo   |   Start   |   End
---------+-----------+----------
   AA    |   AA0000  | AA9999
   AB    |   AB0000  | AB9999
   AC    |   AC0000  | AC9999
   AD    |   AD0000  | AD9999
    --------------------
    --------------------
    ------- so on ------
   ZZ    |   ZZ0000  | ZZ9999

Из этой исходной таблицы я хочу создать вид результата цикла, где каждый HeadNo будет возвращать 10000 результат для каждого, начиная с 0000 до 9999.

Результат должен выглядеть как:

HeadNo   |   Actual Code
---------+---------------
   AA    |   AA0000
   AA    |   AB0001
   AA    |   AC0002
   AA    |   AD0003
    --------------------
    --------------------
    ------- so on ------
   AA    |   AA9998
   AA    |   AA9999

как мудрый для каждого HeadNo

   ZZ    |   ZZ0000
   ZZ    |   ZZ0001
   ZZ    |   ZZ0002
   ZZ    |   ZZ0003
    --------------------
    --------------------
    ------- so on ------
   ZZ    |   ZZ9999

Я хочу объединить и вставить в одну отдельную единую таблицу.

Будет ли значение Actual Code всегда иметь формат AA0000?

Larnu 19.02.2019 10:39

@Cid: да, я меняю первую строку вывода,

Irfan 20.02.2019 01:29

@Larnu: да, формат всегда будет с 2 заглавными буквами и 4 цифрами... например, от AA0000 до ZZ9999

Irfan 20.02.2019 01:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

ЕСЛИ для каждой строки требуются значения 0-9999, тогда вам просто нужно ПЕРЕКРЕСТИТЬ СОЕДИНЕНИЕ с таблицей подсчета:

WITH N AS(
    SELECT *
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1
         CROSS JOIN N N2 --100
         CROSS JOIN N N3 --1000
         CROSS JOIN N N4 --10000
    )
SELECT YT.HeadNo,
       YT.HeadNo + RIGHT('0000' + CONVERT(varchar(4),T.I),4) AS ActualCode
FROM YourTable YT
     CROSS JOIN Tally T;

Однако, если у вас есть фактические начальный и конечный диапазоны для HeadNo (как в примере ниже), вам нужно будет использовать немного больше логики в JOIN:

WITH VTE AS (
    SELECT *
    FROM (VALUES('AA','AA0000','AA9999'),
                ('AB','AB0000','AB5000'), --Guesssing this is more realistic
                ('AC','AC1000','AC8000'), 
                ('AD','AD0000','AD0100'),
                ('ZZ','ZZ0000','ZZ9999')) V(HeadNo, HeadStart, HeadEnd)),
N AS(
    SELECT *
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1
         CROSS JOIN N N2 --100
         CROSS JOIN N N3 --1000
         CROSS JOIN N N4 --10000
    )
SELECT V.HeadNo,
       V.HeadNo + RIGHT('0000' + CONVERT(varchar(4),T.I),4) AS ActualCode
FROM VTE V
     JOIN Tally T ON T.I BETWEEN STUFF(V.HeadStart,1,2,'') AND STUFF(V.HeadEnd,1,2,'')
ORDER BY V.HeadNo,
         ActualCode;

Второй пример предполагает, который HeadNo всегда будет иметь формат AA0000; если это не так, то нам не хватает важной информации, которую следует включить в ваш вопрос.

Большое спасибо, ваш запрос выше работал в соответствии с моим требованием.

Irfan 20.02.2019 02:09

Попробуйте код ниже. Я использовал рекурсивный CTE, чтобы получить числа от 0 до 9999, а затем cross join добавить в ваш столбец HeadNo:

;with cte as (
  select 0 n
  union all 
  select n + 1 from cte
  where n < 9999
)

select HeadNo, HeadNo + right('0000' + cast(n as varchar(4)), 4) from MyTable
cross join cte option (maxrecursion 0)

Это не даст ожидаемых результатов. ОП хочет строки формата 'AA0000' Значение int0, приведенное к varchar(4), является значением '0', дающим окончательный результат 'AA0'. Кроме того, такой CTE является скрытой формой RBAR; итоговая таблица позволит избежать требования OPTION (MAXRECURSION 0) и, вероятно, обеспечит преимущество в производительности.

Larnu 19.02.2019 10:58

@Michał Turczyn использует Order by, чтобы получить ожидаемый результат.

Mano 19.02.2019 11:28

Другие вопросы по теме