Получить имена столбцов и данные в строки в SQL - PullRequest
0 голосов
/ 07 марта 2020

У меня есть таблица с базовыми c сведениями о сотруднике, как показано ниже:

Таблица: tblEmployees

EmpID   Name    Contact   Sex
100     John    55555     M
200     Kate    44444     F
300     Sam     88888     M

Я хотел бы получить результат моего запроса следующим образом для конкретного сотрудника, где EmpID = 200

Col1    Col2
EmpID   200
Name    Kate
Sex     F

Ответы [ 3 ]

5 голосов
/ 07 марта 2020

Вы можете использовать перекрестное применение:

select t.*
from employees e
cross apply (values 
    ('empid', cast(empid as varchar(100))),
    ('name', name), 
    ('sex', sex)
) t(attr, value)
where e.empid = 200

Предположительно, empid - это число, поэтому необходимо явное приведение (в противном случае sql сервер попытается преобразовать имя и пол в числа, что потерпит неудачу).

Демонстрация на DB Fiddle :

attr  | value
:---- | :----
empid | 200  
name  | Kate 
sex   | F    
0 голосов
/ 07 марта 2020

Или менее сложное решение, включающее 3 UNION, при условии, что имена полей заранее определены. Это может работать лучше на больших столах. Если у вас есть проблемы с производительностью, проанализируйте план выполнения и убедитесь, что индексы используются оптимально.

Поскольку вы ищете только одного конкретного сотрудника за раз:

SELECT 'empid', convert(varchar(12), EmpID)
FROM tblEmployees
WHERE EmpID = 200
UNION ALL
SELECT 'name', name
FROM tblEmployees
WHERE EmpID = 200
UNION ALL
SELECT 'sex', sex
FROM tblEmployees
WHERE EmpID = 200

Первая строка делает convert(varchar(12) в предположении, что EmpID является полем int.

0 голосов
/ 07 марта 2020

Другой вариант с небольшим XML

Полное раскрытие: Не так эффективно, как у GMB CROSS APPLY (+1) или UNPIVOT. НО он динамически отключает практически любую строку, таблицу, представление или произвольный запрос c без фактического использования Dynami c SQL.

Пример

Declare @YourTable Table ([EmpID] varchar(50),[Name] varchar(50),[Contact] varchar(50),[Sex] varchar(50))  Insert Into @YourTable Values 
 (100,'John',55555,'M')
,(200,'Kate',44444,'F')
,(300,'Sam',88888,'M')

 Select A.EmpID
       ,C.*
 From @YourTable A
 Cross Apply ( values (convert(xml,(select a.* for XML Raw ))) ) B(XMLData)
 Cross Apply (
                Select Item  = xAttr.value('local-name(.)', 'varchar(100)')
                      ,Value = xAttr.value('.','varchar(max)')
                 From  XMLData.nodes('//@*') xNode(xAttr)
                 Where xAttr.value('local-name(.)', 'varchar(100)') not in ('EmpID','Other','Columns2Exclude')
             ) C

Возвращает

EmpID   Item    Value
100     Name    John
100     Contact 55555
100     Sex     M
200     Name    Kate
200     Contact 44444
200     Sex     F
300     Name    Sam
300     Contact 88888
300     Sex     M

РЕДАКТИРОВАТЬ - Если интересует здесь подход TVF

Select A.EmpID
      ,B.*
 From  @YourTable A
 Cross Apply [dbo].[tvf-XML-UnPivot-Row]((Select A.* for XML RAW)) B

TVF

CREATE FUNCTION [dbo].[tvf-XML-UnPivot-Row](@XML xml)
Returns Table 
As
Return ( 
        Select Item  = xAttr.value('local-name(.)', 'varchar(100)')
              ,Value = xAttr.value('.','varchar(max)')
         From  @XML.nodes('//@*') xNode(xAttr)
)
...