Наилучший способ выполнения вычислений для длинной серии последовательных столбцов в предложении select - PullRequest
0 голосов
/ 15 января 2020

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

Например,

Employee ID  | Upper Limit | ... | Week 1 | Week 2 | Week 3 | Week .. | ... | Week 52 | isActive |
8971239        70000               100      200      100      400             500       1
7823468        60000               200      300      100      200             400       1
8187119        20000               300      300      300      300             200       1

Когда мне нужно вычислить, например, СУММУ все недели для определенного c сотрудника, чтобы избежать написания следующего кода:

SELECT [Week 1] + [Week 2] + [Week 3] + ... + [Week 52] FROM tblWeeklySalaries where EmployeeID = 8971239

Я создаю строку внутри al oop, которая будет использоваться в качестве сценария для выполнения. Примерно так:

DECLARE @script nvarchar(max)
SET @script = 'SET @periodou = (SELECT '

WHILE @tempWeek <= @week
BEGIN

    IF @tempWeek <= 52
    BEGIN
        SET @script = @script + 'ISNULL([Week ' + CONVERT(NVARCHAR, @tempWeek) + '], 0) +'  
    END
    SET @tempWeek = @tempWeek + 1
END

SET @script = LEFT(@script, LEN(@script) - 1)
SET @script = @script + ' AS [Salary] FROM tblWeeklySalaries 
                                      WHERE [EmployeeID ] = ' + CONVERT(NVARCHAR, @EmployeeID)

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

Таким образом, я Я ищу способ добавить, например, ряд столбцов в таблице c. Что-то вроде

SELECT (COLUMNS(4, 56) FROM INFORMATION.SCHEMA WHERE TABLE_NAME = 'tblWeeklySalaries') FROM tblWeeklySalaries where EmployeeID = 8971239

Есть совет? Большое спасибо

Ответы [ 2 ]

0 голосов
/ 15 января 2020

У вас плохая структура данных, и вы должны это исправить. Таблица SQL почти никогда не должна иметь повторяющихся столбцов. Поместить значения в отдельные строки намного проще.

В любом случае вы можете написать представление, чтобы сделать это эффективно, используя apply:

create view v_WeeklySalaries as
    select ws.employee_id, . . . ,  -- other columns you want from tblWeeklySalaries
           v.*      
    from tblWeeklySalaries ws cross apply
         (values ('Week 1', ws.[Week 1]),
                 ('Week 2', ws.[Week 2]),
                 . . . 
         ) v(week, salary);

Затем вы можете использовать это представление. Возможно, вам придется пересматривать представление каждую неделю - в вашей модели данных неясно, как добавляются новые недели. По крайней мере, вам нужно будет делать это, пока вы не исправите свою модель данных.

0 голосов
/ 15 января 2020

Вы нарушаете первую нормальную форму протезом ... Последствия будут:

  • трудности при написании запросов
  • важные потери производительности
  • аномалии транзакций

Тот факт, что у вас есть столбцы с несколькими столбцами, вызывает "Неделя ... n " означает, что вы хотите, чтобы значения были кратны одной и той же информации , которая отличается по одному критерию .

На самом деле это можно заменить на массив из недель, ограниченный от 1 до 52. Но первая нормальная форма говорит, что в столбце всегда должны быть только значения ATOMI C. ARRAYS содержит несколько значений, поэтому они не являются атомами c. У вас есть скрытый массив с использованием такой структуры вашей таблицы. Это типичное нарушение первой нормальной формы протезом…

При правильном проектировании вашей базы данных:

CREATE TABLE T_EMPLOYEE_PAYS 
(EMP_ID,    YEAR,    WEEK_NUMBER,    SALARY)

Запрос будет очень быстро написать:

SELECT EMP_ID,  YEAR,  SUM(SALARY)
FROM   T_EMPLOYEE_PAYS 
GROUP  BY EMP_ID,  YEAR

И у вас не будет проблем с индексацией производительности и потерей данных в транзакциях.

Помните, что реляционная база данных не является электронной таблицей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...