2013-03-29 4 views
1

Я очень новичок в SQL, и я не уверен, как выполнить следующую задачу: у меня есть набор данных в таблице, и мне нужно преобразовать данные в одно из двух значений, а затем суммировать итоговые значения для каждой строки в паре сводных столбцов. Смотрите ниже:SQL - преобразование значений, количество экземпляров в нескольких столбцах

tbl1:

row P1 P2 P3 
--- --- --- --- 
1  a  b  c 
2  a  a  a 
3  b  c  b 
4  a  b  b 
5  NULL NULL NULL 

с таблицей преобразования, как:

PNum PType 
---- ----- 
a  car 
b  truck 
c  car 

Желаемый конечный результат:

row P1 P2 P3 numCars numTrucks 
--- --- --- --- ------- --------- 
1  a  b  c  2   1 
2  a  a  a  3   0 
3  b  c  b  1   2 
4  a  b  b  1   2 
5  NULL NULL NULL NULL  NULL 

код, чтобы получить тестовые таблицы:

DECLARE @tbl1 TABLE(P1 VARCHAR,P2 VARCHAR,P3 VARCHAR) 

INSERT INTO @tbl1 
SELECT 'a','b','c' UNION ALL 
SELECT 'a','a','a' UNION ALL 
SELECT 'b','c','b' UNION ALL 
SELECT 'a','b','b' 


DECLARE @tbl2 TABLE(PNum VARCHAR,PType NVARCHAR(100)) 

INSERT INTO @tbl2 
SELECT 'a','car' UNION ALL 
SELECT 'b','truck' UNION ALL 
SELECT 'c','car' 

Я изучаю PIVOT, но мне трудно понять, как его реализовать (особенно с помощью конверсионного элемента). Я думал о попытке сначала вставить набор столбцов только для преобразования значений (например, «P1_converted»), а затем попытаться суммировать их, но моя фактическая таблица имеет 10 столбцов этого типа, и я не хотел добавлять дополнительные 10 столбцов к столу, если есть более простой способ. Есть предположения? Благодаря!

Я использую SQL Server 2008.

+1

Вы можете нормализовать свой стол? – Kermit

+1

Если вы не понимаете, комментируя комментарий PolishPrince, я слышал хорошие вещи о книге «Дизайн базы данных для простых смертных». –

+1

Также [остановите объявление столбцов, переменных, параметров и т. Д. Как 'VARCHAR' без длины] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring -varchar-без length.aspx). В этом случае вам повезло, что вам нужны только односимвольные значения в «P1, P2, P3». Попробуйте вставить '' xy'' в один из них. –

ответ

1

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

Вы можете использовать функцию UNPIVOT, но так как вы используете SQL Server 2008, вы можете использовать CROSS APPLY и VALUES для преобразования P1, P2 и P3 из столбцов в строки. Код для преобразования данных является:

select * 
from tbl1 
cross apply 
(
    values ('p1', p1), ('p2', p2), ('p3', p3) 
) c(col, value) 

См SQL Fiddle with Demo. Это преобразует данные в формат:

| P1 | P2 | P3 | COL | VALUE | 
------------------------------ 
| a | b | c | p1 |  a | 
| a | b | c | p2 |  b | 
| a | b | c | p3 |  c | 
| a | a | a | p1 |  a | 

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

select rn, p1, p2, p3, 
    sum(case when t.ptype = 'car' then 1 else 0 end) numCars, 
    sum(case when t.ptype = 'truck' then 1 else 0 end) numTrucks 
from 
(
    select p1, p2, p3, 
    row_number() over(order by p1, p2, p3) rn 
    from tbl1 
) d 
cross apply (values ('p1', p1), ('p2', p2), ('p3', p3)) c(col, value) 
inner join tbl2 t 
    on c.value = t.pnum 
group by rn, p1, p2, p3 

См SQL Fiddle with Demo. Это дает результат:

| RN | P1 | P2 | P3 | NUMCARS | NUMTRUCKS | 
------------------------------------------- 
| 1 | a | a | a |  3 |   0 | 
| 2 | a | b | b |  1 |   2 | 
| 3 | a | b | c |  2 |   1 | 
| 4 | b | c | b |  1 |   2 | 
+1

Awesome - это именно то, что мне нужно. Спасибо! – Seth

1

Вот несколько иной подход с использованием PIVOT:

SELECT * FROM 
(
    SELECT d.[row], d.P1, d.P2, d.P3, t.PType, 
    [tc] = CASE WHEN t.PNum = d.P1 THEN 1 ELSE 0 END 
     + CASE WHEN t.PNum = d.P2 THEN 1 ELSE 0 END 
     + CASE WHEN t.PNum = d.P3 THEN 1 ELSE 0 END 
    FROM @tbl1 d CROSS JOIN @tbl2 t 
) AS x 
PIVOT (SUM([tc]) FOR PType IN ([car],[truck])) AS p; 
+1

Стержень? Я в шоке! :) – Taryn

+0

[Вы видели мой ответ вчера] (http://stackoverflow.com/a/15689664/61305)? :-) –

+0

Я этого не видел! – Taryn

Смежные вопросы