SQL: Создание «строки вычисления»

#sql

Вопрос:

У меня есть стол, который выглядит так

 TYPE | A | B | C | ... | Z
one  | 4 | 4 | 4 | ... | 4
two  | 3 | 2 | 2 | ... | 1
 

И я хотел вставить строку с вычислением (строка один минус строка два):

 TYPE | A | B | C | ... | Z
one  | 4 | 4 | 4 | ... | 4
two  | 3 | 2 | 2 | ... | 1
delta| 1 | 2 | 2 | ... | 3
 

Я думал о команде SQL, которая выглядит так

 (select A from table where type=one) - (select A from table where type=two)
 

Недостатком является то, что это слишком долго, и мне также приходится делать это для всех столбцов (A-Z), а это довольно много.

Я уверен, что есть более элегантный способ сделать это.

пс:

Последовательность моего кода выглядит так, кстати:

 // I'm inserting the data from a RawTable to a TempTable

INSERT one
INSERT two
INSERT delta
INSERT three
INSERT four
INSERT delta
...
INSERT onehundredone
INSERT onehundredtwo
INSERT delta
 

Комментарии:

1. Предположительно, вы не хотите хранить эти данные, просто включите их в результирующий набор? Кроме того, я думаю , что ваша нумерация изменилась ... , так как, если вы работаете попарно, onehundredone и onehundredtwo должны быть парой.

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

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

Ответ №1:

Я добавил столбец идентификатора с identity в вашу временную таблицу. Вы можете использовать это, чтобы выяснить, какие строки следует сгруппировать.

 create table YourTable
(
  ID int identity primary key,
  [TYPE] varchar(20),
  A int,
  B int,
  C int
)

insert into YourTable ([TYPE], A, B, C)
select 'one',   4, 4, 4 union all
select 'two',   3, 2, 2 union all
select 'three', 7, 4, 4 union all
select 'four',  3, 2, 2 union all
select 'five',  8, 4, 4 union all
select 'six',   3, 2, 2


select T.[TYPE], T.A, T.B, T.C
from
  (
    select
      T.ID,
      T.[TYPE],
      T.A,
      T.B,
      T.C
    from YourTable as T  
    union all  
    select
      T2.ID,
      'delta' as [TYPE],
      T1.A-T2.A as A,
      T1.B-T2.B as B,
      T1.C-T2.C as C
    from YourTable as T1
      inner join YourTable as T2
        on T1.ID = T2.ID-1 and
           T2.ID % 2 = 0
  ) as T
order by T.ID, case T.[TYPE] when 'delta' then 1 else 0 end
 

Результат:

 TYPE                 A           B           C
-------------------- ----------- ----------- -----------
one                  4           4           4
two                  3           2           2
delta                1           2           2
three                7           4           4
four                 3           2           2
delta                4           2           2
five                 8           4           4
six                  3           2           2
delta                5           2           2
 

Сортировка по столбцу C из первой строки в группе:

 select T.[TYPE], T.A, T.B, T.C
from
  (
    select
      T1.ID,
      T1.[TYPE],
      case T1.ID % 2 when 1 then T1.C else T2.C end as Sortorder,
      T1.A,
      T1.B,
      T1.C
    from YourTable as T1
      left outer join YourTable as T2
        on T1.ID = T2.ID 1  
    union all  
    select
      T2.ID,
      'delta' as [TYPE],
      T1.C as Sortorder,
      T1.A-T2.A as A,
      T1.B-T2.B as B,
      T1.C-T2.C as C
    from YourTable as T1
      inner join YourTable as T2
        on T1.ID = T2.ID-1 and
           T2.ID % 2 = 0
  ) as T
order by T.Sortorder, T.ID, case T.[TYPE] when 'delta' then 1 else 0 end
 

Комментарии:

1. Плюс один за то, что он попал в точку!

2. могу я задать вам еще один вопрос, можно ли отсортировать группы (one, two, delta) в соответствии со значением column C и row 1 этой группы?

Ответ №2:

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

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

Один ярлык, если вам просто нужно создать процедуру или функцию, которая делает это (т. Е. Построить один раз, запустив много), вы можете скопировать список столбцов в электронную таблицу (Excel), создать повторяющиеся инструкции, используя форумы, которые ссылаются на имена столбцов, а затем скопировать результаты обратно. (Это гораздо проще сделать, чем объяснить.)

Ответ №3:

Я понятия не имею, зачем вы это делаете, но я бы подошел к этому так:

 insert into table
select 'delta', 
t1.a - t2.a, 
t1.b - t2.b
.....
from table t1, 
table t2
where t1.type = 'one'
and t2.type = 'two'
 

Вам придется выполнить этот запрос сразу после вставки «один» и «два», а затем повторно запустить его после вставки «три» и «четыре». Мерзкая мерзкая мерзость.

Если вы можете каким-либо образом переименовать столбцы или создать числовой столбец, вы можете запустить его в одном запросе.

Комментарии:

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

2. Ну, вы могли бы сделать это в интерфейсе, но ваше решение звучит так же разумно, как и любое другое… вам нужно придумать способ упорядочения результирующего набора и вставки строк «дельта» в нужном месте.

Ответ №4:

Когда вы замените один на 1, два на 2 и так далее, тогда, возможно, этот sql сможет работать:

 INSERT INTO PodMays
SELECT
  "Delta", A.A-B.A, A.B-B.B, A.C-B.C, A.D-B.D, A.E-B.E
FROM
  (
    SELECT TOP 1
      * 
    FROM
      (SELECT TOP 2 * FROM PodMays WHERE Type <> "Delta" ORDER BY Type DESC)
    ORDER BY
      Type ASC
  ) AS A,
  (
    SELECT TOP 1 
      * 
    FROM 
      (SELECT TOP 2 * FROM PodMays WHERE Type <> "Delta" ORDER BY Type DESC)
    ORDER BY 
      Type DESC
  ) AS B