ahmed_sa Ответов: 2

Как отдельное поле partdone к тексту, да или нет, или нуль, в зависимости от положения ?


Я работаю на SQL server 2012 и у меня есть табличные части с двумя полями

partId int
PartDone nvarchar(50)


partId    partDone
555444    0012
911877    0221


длина поля partDone составляет 4 числа
Мне нужно сделать петлю в поле partDone

если 0 то нет

если 1 то да

если 2 то ноль

FinalResult
partId    partDone first  second third  four 
555444    0012     no      no     yes   null       
911877    0221     no      null   null  yes


это поле partDone принимает только 0 или 1 или 2

и мне нужно разделить их на да или нет или ноль в зависимости от позиции каждого числа

Что я уже пробовал:

select partId,partDone from Parts

Maciej Los

Неужели мое решение неверно?

2 Ответов

Рейтинг:
5

Richard Deeming

Если PartDone это всегда четыре числа, тогда вам не нужно PIVOT:

DECLARE @tmp TABLE (partId int, PartDone char(4));

INSERT INTO @tmp (partId, partDone)
VALUES
    (555444, '0012'),
    (911877, '0221')
;

SELECT
    partId,
    PartDone,
    CASE Substring(PartDone, 1, 1)
        WHEN '0' THEN 'no'
        WHEN '1' THEN 'yes'
    END As [first],
    CASE Substring(PartDone, 2, 1)
        WHEN '0' THEN 'no'
        WHEN '1' THEN 'yes'
    END As [second],
    CASE Substring(PartDone, 3, 1)
        WHEN '0' THEN 'no'
        WHEN '1' THEN 'yes'
    END As [third],
    CASE Substring(PartDone, 4, 1)
        WHEN '0' THEN 'no'
        WHEN '1' THEN 'yes'
    END As [fourth]
FROM
    @tmp
;
NB: Если это всегда четыре числа, вы не должны определять поле как nvarchar(50) Вы знаете, что он никогда не будет содержать никаких "расширенных" символов, поэтому вам не нужно n префикс. Вы знаете, что длина никогда не будет больше, чем 4, так что вам не нужно место для 50 персонажи. И вы знаете, что длина никогда не будет меньше чем 4, так что вам не нужно поле переменной длины.

Определите это поле следующим образом char(4) вместо.

Лучшим вариантом было бы определить четыре bit поля, и сделать так, чтобы PartDone поле вычисляемый столбец:
DECLARE @tmp TABLE 
(
    PartId int,
    [first] bit,
    [second] bit,
    [third] bit,
    [fourth] bit, 
    PartDone As
    (
        CASE WHEN [first] Is Null THEN '2' ELSE CAST([first] As char(1)) END
        + CASE WHEN [second] Is Null THEN '2' ELSE CAST([second] As char(1)) END
        + CASE WHEN [third] Is Null THEN '2' ELSE CAST([third] As char(1)) END
        + CASE WHEN [fourth] Is Null THEN '2' ELSE CAST([fourth] As char(1)) END
    )
);

INSERT INTO @tmp (PartId, [first], [second], [third], [fourth])
VALUES
    (555444, 0, 0, 1, NULL),
    (911877, 0, NULL, NULL, 1)
;

SELECT
    PartId,
    PartDone,
    CASE [first] WHEN 0 THEN 'no' WHEN 1 THEN 'yes' END As [first],
    CASE [second] WHEN 0 THEN 'no' WHEN 1 THEN 'yes' END As [second],
    CASE [third] WHEN 0 THEN 'no' WHEN 1 THEN 'yes' END As [third],
    CASE [fourth] WHEN 0 THEN 'no' WHEN 1 THEN 'yes' END As [fourth]
FROM 
    @tmp
;


Maciej Los

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

Richard Deeming

Лично я думаю, что один SELECT с четырьмя CASE операторы будут легче следовать, чем рекурсивный CTE и a PIVOT. :)

Maciej Los

;)

Рейтинг:
1

Maciej Los

Вы можете использовать КТОС[^] вместе с СТЕРЖЕНЬ[^] для такого требования. Видеть:

DECLARE @tmp TABLE(partId int, PartDone nvarchar(50))

INSERT INTO @tmp(partId, partDone)
VALUES(555444, '0012'),
(911877, '0221');

;WITH CTE AS
(
	SELECT partId, PartDone, 1 AS LoopNo, LEFT(PartDone, 1) AS pdid, RIGHT(partDone, LEN(PartDone)-1) AS Remainder
	FROM @tmp
	WHERE PartDone IS NOT NULL
	UNION ALL
	SELECT partId, PartDone, LoopNo+1 AS LoopNo, LEFT(Remainder, 1) AS pdid, RIGHT(Remainder, LEN(Remainder)-1) AS Remainder
	FROM CTE 
	WHERE LEN(Remainder)>0
)
SELECT partId, PartDone, [1], [2], [3], [4]
FROM (
	SELECT partId, PartDone, LoopNo, CASE 
		WHEN pdid = 0 THEN 'no' 
		WHEN pdid = 1 THEN 'yes' 
		ELSE null END AS pdid 
	FROM CTE 
) AS dt
PIVOT(MAX(pdid) FOR LoopNo IN ([1], [2], [3], [4])) AS pt


Результат:
partId	PartDone	1	2		3		4
555444	0012		no	no		yes		NULL
911877	0221		no	NULL	NULL	yes


phil.o

5 б

Maciej Los

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

MadMyche

+5

Maciej Los

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