2013-06-21 3 views
3

У меня есть один столбец данных в SQL Sever и нужно развернуть это на несколько столбцов (2).Преобразование одного столбца в несколько в SQL Server

Необработанные данные выглядит так:

Col1 
------- 
Monday 
Jon 
Boris 
Natalie 
Tuesday 
James 
Tom 
Boris 

Я хотел бы, чтобы она выглядела так:

Name | Day 
-------+--------- 
Jon | Monday 
Boris | Monday 
Natalie| Monday 
James | Tuesday 
Tom | Tuesday 
Boris | Tuesday 

Большое спасибо заранее.

+3

Откуда вы знаете, что «Джон» привязан к «Понедельник» и т. Д.? Это связано с тем, как они перечислены в таблице? Данные в таблице по порядку не упорядочены, у вас есть столбец, который будет хранить данные в этом порядке - столбец идентичности? – Taryn

+0

Да, он импортируется из списка текстовых файлов. Таким образом, каждый понедельник в понедельник и каждый вторник во вторник. Предполагая, что я импортирую данные в порядке по строкам, я могу получить eailsy и столбца ID, который увеличивается. – pugu

+1

Лично я бы создал вторую таблицу с днями недели, дал им технический ключ и связал их с FK, вместо того, чтобы повторять имя дня в каждой записи. –

ответ

4

Предполагая, что вы собираетесь быть в состоянии добавить, что столбец идентификации источника таблицу для заказа и что таблица будет выглядеть примерно нг так:

CREATE TABLE Table1 (id int identity(1,1), Col1 NVARCHAR(50)) 

INSERT INTO Table1 (Col1) 
VALUES 
    ('Monday'),('Jon'),('Boris'),('Natalie'), 
    ('Tuesday'),('James'),('Tom'),('Boris') 

Вы можете попробовать следующее:

  • Сначала нужно создать временную таблицу для будней, так что вы можете отличить их (также может быть сделано другими способами)
  • Регистрация дней назад с исходной таблицей ищет большие идентификаторы (t.ID> d1.ID)
  • Предотвратить те, которые должны идти в следующий день ID (t.ID < MIN (d2.Id))
  • Coalesce нужно только убедиться, что он работает в последний день в списке.

.

CREATE TABLE #weekDays (wd NVARCHAR(10)); 

INSERT INTO #weekDays 
VALUES 
    ('Monday'), ('Tuesday'), ('Wednesday'), 
    ('Thursday'), ('Friday'), ('Saturday'), ('Sunday'); 

WITH CTE_Days AS 
(
    SELECT t.* 
    FROM Table1 t 
    INNER JOIN #weekDays wd ON wd.wd = t.col1 
) 
SELECT * 
FROM CTE_Days d1 
INNER JOIN Table1 t ON t.id > d1.id AND t.id < 
    COALESCE((
     SELECT MIN(d2.id) 
     FROM CTE_Days d2 
     WHERE d2.id > d1.id 
    ), t.id + 1) 
+2

+1 - интересный ответ. – Devart

+1

Это блестящий ответ, спасибо вам большое! У меня была довольно долгая процедура, включающая переменные и циклы. Это было ужасно! – pugu

2

Попробуйте один -

Запрос:

DECLARE @temp TABLE (Col1 NVARCHAR(50)) 

INSERT INTO @temp (Col1) 
VALUES 
    ('Monday'),('Jon'),('Boris'),('Natalie'), 
    ('Tuesday'),('James'),('Tom'),('Boris') 

;WITH cte AS 
(
    SELECT 
      Col1 
     , rn = ROW_NUMBER() OVER (ORDER BY 1/0) % 4 
     , rn2 = ROW_NUMBER() OVER (ORDER BY 1/0) 
    FROM @temp 
) 
SELECT 
     [Day] = t.Col1 
    , Name = t2.Col1 
FROM cte t 
OUTER APPLY (
    SELECT * 
    FROM cte t2 
    WHERE t2.rn2 BETWEEN t.rn2 + 1 AND t.rn2 + 3 
) t2 
WHERE t.rn = 1 

Выход:

output

+0

Это, безусловно, делает то, что я хочу, единственная проблема - если у нас есть переменное количество людей в разные дни. Поэтому, если мы добавим «Майк» в список для «Понедельника», он ломается. Я думаю, что в этом случае мне, вероятно, понадобится сделать цикл и подсчитать количество людей в каждом разделе. – pugu