2013-05-07 2 views
2

Я пишу хранимую процедуру, где у меня есть столбец с именем scale, который сохраняет результат с помощью переключателя, выбранного как 1/2/3/4 для каждого типа Название навыка.Сохраненная процедура получения суммы записей в таблице для каждого ID

Теперь я хочу видеть общее количество людей под каждой шкалой - 1 и 2 и 3 и 4 для определенного навыка 1, умения 2, ..., skillname20.

Вот мой стол:

tblSkill:

ID | SkillName 

и другой стол, как:

tblskillMetrics:

ID | SkillID | EmployeeID | Scale 

А вот запрос пытаюсь написать:

Create Procedure spGetSkillMetricsCount 
As 
Begin 
    SELECT 
     tblSkill.Name as skillname, 
     (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=1) AS NotAplicable, 
     (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=2) AS Beginner, 
     (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=3) AS Proficient, 
     (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=4) AS Expert 
    FROM 
     tblSkill 
    INNER JOIN 
     tblSkillMetrics ON tblSkillMetrics.SkillID = tblSkill.ID 
    GROUP BY 
     tblSkillMetrics.Scale, tblSkill.Name 
    ORDER BY 
     skillname DESC 
END 

Используя эту хранимую процедуру, я могу получить желаемый формат, в котором я хочу получить результат, но в результатах для каждого: Неприменимо, Новичок, Профессионал или Эксперт - это то же самое, и это сумма всех сделанных записей в таблице.

Пожалуйста, кто-нибудь может предложить, где я иду не так.

ответ

2

Логически, вы группируетесь по двум критериям, по шкале и имени навыка. Однако, если я правильно понимаю, каждая строка должна представлять одно имя навыка. Поэтому вам следует группировать только tblSkill.Name. Чтобы получить разные значения для разных шкал в отдельных столбцах, вы можете использовать условную агрегацию , т. Е. Агрегирование на выражение, которое (обычно) включает в себя конструкцию CASE. Вот как вы могли бы это сделать:

SELECT 
    tblSkill.Name AS skillname, 
    COUNT(CASE tblSkillMetrics.Scale WHEN 1 THEN EmployeeID END) AS NotAplicable, 
    COUNT(CASE tblSkillMetrics.Scale WHEN 2 THEN EmployeeID END) AS Beginner, 
    COUNT(CASE tblSkillMetrics.Scale WHEN 3 THEN EmployeeID END) AS Proficient, 
    COUNT(CASE tblSkillMetrics.Scale WHEN 4 THEN EmployeeID END) AS Expert 
FROM 
    tblSkill 
INNER JOIN 
    tblSkillMetrics ON tblSkillMetrics.SkillID = tblSkill.ID 
GROUP BY 
    tblSkill.Name 
ORDER BY 
    skillname DESC 
; 

Обратите внимание, что для запросов такого типа существует специальный синтаксис. Он использует ключевое слово PIVOT, поскольку то, что вы получаете, по существу представляет собой сгруппированный результирующий набор, повернутый по одному из критериев группировки, в этом случае масштабируется. Это как то же самое может быть достигнуто с PIVOT:

SELECT 
    skillname, 
    [1] AS NotAplicable, 
    [2] AS Beginner, 
    [3] AS Proficient, 
    [4] AS Expert 
FROM (
    SELECT 
     tblSkill.Name AS skillname, 
     tblSkillMetrics.Scale, 
     EmployeeID 
    FROM 
     tblSkill 
    INNER JOIN 
     tblSkillMetrics ON tblSkillMetrics.SkillID = tblSkill.ID 
) s 
PIVOT (
    COUNT(EmployeeID) FOR Scale IN ([1], [2], [3], [4]) 
) p 
; 

В принципе, PIVOT подразумевает группировку. Все столбцы, кроме одного в исходном наборе данных, являются критериями группировки, а именно каждый из них, который не используется в качестве аргумента агрегатной функции в предложении PIVOT, является критерием группировки. Один из них также присваивается тому, на который повернуты результаты. (Опять же, в этом случае это шкала.)

Поскольку группировка неявна, производная таблица используется, чтобы избежать группировки по большему количеству критериев, чем это необходимо. Значения Scale становятся именами новых столбцов, которые создает предложение PIVOT. (Именно поэтому они разделяются с помощью квадратных скобок, когда перечисленные в PIVOT:. Они не являются идентификаторы в этом контексте, но идентификаторы delimited as required by Transact-SQL syntax)

+0

Спасибо @ Andriy M, что очень помогло. Я тоже пробовал что-то подобное, но кое-что допустил, поэтому не смог добиться результата. И спасибо за то, что объяснил мне все. – Novice

1

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

select tblSkill.name skillname 
, case when tblSkillMetrics = 1 then 'Not Applicable' 
etc 
else 'Expert' end level 
, count(employeeid) records 
from tblSkill join tblSkillMetrics 
on tblSkillMetrics.SkillID = tblSkill.ID 
group by tblSkill.name 
, case when tblSkillMetrics = 1 then 'Not Applicable' 
etc 
else 'Expert' end level 
order by skillname desc 
+0

Благодаря @Dan Bracuk для вашего Помогите. – Novice

0

Вы можете использовать что-то вроде этого:

SELECT sum(case when tblskillmetrics.scale = 2 then 1 else 0 end) Beginner, 
     sum(case when tblskillmetrics.Scale=3 then 1 else 0 end)Proficient, 
     SUM(case when tblSkillMetrics.Scale=4 then 1 else 0 end)Expert, 
     tblSkillGroup.ID AS GroupID,tblSkillGroup.Name AS GroupName, 
     tblSkill.ID AS SkillID 
     , tblSkill.Name AS SkillName 

FROM tblSkill INNER JOIN tblSkillMetrics 
     ON tblSkillMetrics.SkillID=tblSkill.ID 
ORDER BY GroupName DESC 
Смежные вопросы