Цикл SQL Server через таблицу для каждых 5 строк - PullRequest
0 голосов
/ 10 декабря 2018

Мне нужно написать хранимую процедуру или табличную функцию, чтобы вернуть новую таблицу данных в качестве нового источника данных.Я хочу перебрать исходную таблицу для каждых 5 строк в столбце идентификатора счета-фактуры (возможно, не начиная с 1), первые 5 строк добавляются слева от новой таблицы, а вторые 5 строк добавляются справа отновая таблица, третьи 5 строк слева и т. д.

Например, вот исходная таблица: Original Table

Вот таблица ожидаемых значений:Result table

Заранее спасибо!

Ответы [ 6 ]

0 голосов
/ 10 декабря 2018

Вот мое решение

Сначала я создаю GRPS, основываясь на том, делится ли in_invoiceid на 5 или нет. (Игнорировать остатки)

После этого я создаю категорию для указания альтернативыгруппы (т. е. путем проверки, равен ли остаток 0 или иным образом)

Затем необходимо выполнить плотную сортировку записей на основе поля категории, упорядоченного in_invoiceid

Наконец, соединение с категорией = 1строки с таким же плотным_ранком, что и записи в категории = 0

create table Invoicetable(IN_ID varchar(100), IN_InvoiceID int)


INSERT INTO Invoicetable (IN_ID, IN_InvoiceID)
VALUES
    ('2345-BCDE-6645-1DDF', 1),
    ('2345-BCDE-6645-3DDF', 2),
    ('2345-BCDE-6645-4DDF', 3),
    ('2345-BCDE-6645-5DDF', 4),
    ('2345-BCDE-6645-6DDF', 5),
    ('2345-BCDE-6645-7DDF', 6),
    ('2345-BCDE-6645-aDDF', 7),
    ('2345-BCDE-6645-sDDF', 8),
    ('2345-BCDE-6645-dDDF', 9),
    ('2345-BCDE-6645-dDDF', 10),
    ('2345-BCDE-6645-dDDF', 11),
    ('2345-BCDE-6645-dDDF', 12);

with data
  as (
select *
      ,(in_invoiceid-1)/5 as grp
      ,case when ((in_invoiceid-1)/5)%2=0 then '1' else '0' end as category
      ,dense_rank() over(partition by  case when ((in_invoiceid-1)/5)%2=0 then '1' else '0' end
                    order by in_invoiceid) as rnk
  from invoicetable a
      )
   select *
      from data a
 left join data b
        on a.rnk=b.rnk       
       and b.category=0
     where a.category=1   

Вот дидблинговая ссылка дБ.

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=287f101737c580ca271940764b2536ae

0 голосов
/ 10 декабря 2018
declare @rowCount int = 5;
with cte as (
    select *,( (IN_InvoiceID-1) / @rowCount ) % 2 group1
        ,( (IN_InvoiceID-1) / @rowCount ) group2
        ,IN_InvoiceID % @rowCount group3
    from T 
)
select * from cte
select T1.INID,T1.IN_InvoiceID,T1.IN_InvoiceAmount,T2.INID,T2.IN_InvoiceID,T2.IN_InvoiceAmount
from CTE  T1
left join CTE T2 on T2.group1 = 1 and T1.group2 = T2.group2-1 and T1.group3 = T2.group3
where T1.group1 = 0

Тест DDL

CREATE TABLE T
    ([INID] varchar(38), [IN_InvoiceID] int, [IN_InvoiceAmount] int)
;

INSERT INTO T
    ([INID], [IN_InvoiceID], [IN_InvoiceAmount])
VALUES
    ('DB3E17E6-35C5-41:121-93B1-F809BF6B2972', 1, 2999),
    ('3212F048-8213-4FCC-AB64-121485B77D4E43', 2, 3737),
    ('E3526373-A204-40F5-801C-7F8302A4E5E2', 3, 3175),
    ('76CC9C19-BF79-4E8A-8034-A33805AD3390', 4, 391),
    ('EC7A2FBC-B62D-4865-88DE-A8097975F125', 5, 1206),
    ('52AD3046-21331-4F0A-BD1D-67F232C54244', 6, 402),
    ('CA48F132-A9F5-4516-9E58-CDEE6644AAD1', 7, 1996),
    ('02E10C31-CAB2-4220-B66A-CEE5E67A9378', 8, 3906),
    ('98F1EEFF-B07A-4B65-87F4-E165264284DD', 9, 2575),
    ('91EBDD8B-B73C-470C-8900-DD66078483DB', 10, 2965),
    ('6E2490E5-C4DE-4833-877F-1590F7BDC1B8', 11, 1603),
    ('00985921-AC3C-4E3E-BAE1-7F58302F831A', 12, 1302)
;

Результат:

2018-12-10.16.19.53-image.png

0 голосов
/ 10 декабря 2018

В идеале вы можете управлять с помощью 2 таблиц Master и Detail Table.

Но из-за моего любопытства я могу решить и дать ответ как

Declare @table table(id int identity, invoice_id int)

; WITH Numbers AS
(
    SELECT n = 1
    UNION ALL
    SELECT n + 1
    FROM Numbers
    WHERE n+1 <= 50
)


insert into @table  SELECT n
FROM Numbers

Select (a.id  )%5 ,* from @table a join @table b on a.id+5 = b.id and a.id != b.id

;WITH Numbers AS
(
    SELECT n = 1, o = 5
    UNION ALL
    SELECT n + 10, o = o+10
    FROM Numbers
    WHERE n+1 <= 50
)

select a.id ParentId,a.invoice_id ParentInvoiceId, --b.n, b.o, 
c.invoice_id childInvoiceID from @table a 
join Numbers b on a.id between b.n and b.o
left join @table c on a.id + 5 = c.id
0 голосов
/ 10 декабря 2018

Вы можете попробовать следующий подход.Разделение таблицы выполняется с помощью (((ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) - 1) / 5) % 2 = 0), который группирует записи в левую и правую группы.

CREATE TABLE #InvoiceTable(
    IN_ID varchar(24),
    IN_InvoiceID int
)


INSERT INTO #InvoiceTable (IN_ID, IN_InvoiceID)
VALUES
    ('2345-BCDE-6645-1DDF', 1),
    ('2345-BCDE-6645-3DDF', 2),
    ('2345-BCDE-6645-4DDF', 3),
    ('2345-BCDE-6645-5DDF', 4),
    ('2345-BCDE-6645-6DDF', 5),
    ('2345-BCDE-6645-7DDF', 6),
    ('2345-BCDE-6645-aDDF', 7),
    ('2345-BCDE-6645-sDDF', 8),
    ('2345-BCDE-6645-dDDF', 9),
    ('2345-BCDE-6645-dDDF', 10),
    ('2345-BCDE-6645-dDDF', 11),
    ('2345-BCDE-6645-dDDF', 12);

WITH cte AS (
    SELECT 
        IN_ID, 
        IN_InvoiceID, 
        CASE
            WHEN (((ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) - 1) / 5) % 2 = 0) THEN 'L'
            ELSE 'R'
        END AS IN_Position
    FROM #InvoiceTable
),
cteL AS (
    SELECT IN_ID, IN_InvoiceID, ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) AS IN_RowNumber
    FROM cte
    WHERE IN_Position = 'L'
),
cteR AS (
    SELECT IN_ID, IN_InvoiceID, ROW_NUMBER() OVER (ORDER BY IN_InvoiceID) AS IN_RowNumber
    FROM cte
    WHERE IN_Position = 'R'
)

SELECT cteL.IN_ID, cteL.IN_InvoiceID, cteR.IN_ID, cteR.IN_InvoiceID
FROM cteL
LEFT JOIN cteR ON (cteL.IN_RowNumber = cteR.IN_RowNumber)

Вывод:

IN_ID               IN_InvoiceID    IN_ID               IN_InvoiceID
2345-BCDE-6645-1DDF 1               2345-BCDE-6645-7DDF 6
2345-BCDE-6645-3DDF 2               2345-BCDE-6645-aDDF 7
2345-BCDE-6645-4DDF 3               2345-BCDE-6645-sDDF 8
2345-BCDE-6645-5DDF 4               2345-BCDE-6645-dDDF 9
2345-BCDE-6645-6DDF 5               2345-BCDE-6645-dDDF 10
2345-BCDE-6645-dDDF 11              NULL                NULL
2345-BCDE-6645-dDDF 12              NULL                NULL
0 голосов
/ 10 декабря 2018

Похоже, что вы хотите разбить таблицу на 2 таблицы с чередованием 5 строк.Простой способ сделать это:

  1. Перенести данные во временную таблицу, имеющую дополнительный столбец (скажем, grouping_id)
  2. Обновить идентификатор группировки, чтобы каждые 5 строк имелитот же идентификаторВы можете использовать in_invoiceId % 5 (функция nod).После этого шага первые 5 строк будут иметь grouping_id 0, следующие 5 будут иметь 1, следующие будут иметь 2 (при условии, что идентификатор вашего счета увеличен +1 для всех строк).
  3. Вы можете просто сделать обычный выбор с помощьюусловие where для нечетного и четного grouping_id
0 голосов
/ 10 декабря 2018

Не могли бы вы проверить статью Отображение данных в нескольких столбцах с использованием SQL , на примере которого показано, как разработчик базы данных может отображать список строк данных в столбчатом режиме с использованием функции Row_Number () и арифметического выражения режима

enter image description here

Необходимо добавить дополнительные столбцы из той же строки, которая отличается в образце

...