Помогите с вложенным запросом в MySQL - PullRequest
0 голосов
/ 17 февраля 2011

Я пытаюсь сделать некоторые расчеты, основанные на записи из основной таблицы, и хотел сохранить обработанный результат в отдельной тестовой таблице.

>Table:Master:
>C1          C2         C3     C4
>----------  --------   --     --
>2011-02-19  Test-A     31      3
>2011-02-19  Test-B     34      3
>2011-02-19  Test-C     17      1
>2011-02-15  Test-A*    48 =I   4
>2011-02-15  Test-B     64      6
>2011-02-15  Test-C     55      5
>2011-02-11  Test-A     64 =I2  6
>2011-02-11  Test-B     53      5
>2011-02-11  Test-C     17      1
>2011-02-10  Test-A     12 =I3  1 =J
>2011-02-10  Test-B     02      0
>2011-02-10  Test-C     54      5

Три вида испытаний, проведенных случайным образом в один и тот же день;но для этого случая дата не так важна;Для расчета используются только последние три записи теста.Я пытаюсь выполнить последовательные вычисления, как показано ниже;используя 3-й самый старый элемент.например, для теста A I (итерация) будет 48 (3-я самая старая запись = столбец c3), и поэтому R2 и R3 будут рассчитываться на основе I2 и I3.И, наконец, отображение среднего значения, R, R2, R3 - J. (C4 = последняя запись.)

Ожидаемый результат:

>Table:Test-A
>SR  Date        I      I2           I3          I4
>--  ----------  -----  -----------  ----------- -------------------        
>1   2011/02/17  48     -52.96       -24.18      -10.71

>Formula:
>SR  Date        R      R2           R3          R4
>--  ----------  -----  -----------  ----------- -------------------        
>1   today()     48=C3  (I*0.23-I2)  (I*0.23-I3) =avg(I,I1,I2,I3)-C4

Я думаю, мне нужно использовать вложенный / вложенный запросс присоединением, но я не мог понять, как справиться со мной;Весь результат будет помещен в отдельные тестовые таблицы.Ваш вклад будет высоко ценится.ТИА

1 Ответ

1 голос
/ 18 февраля 2011

Контрольный пример установки:

CREATE TABLE `m1`
(c1 DATE
,c2 VARCHAR(6)
,c3 SMALLINT
,c4 TINYINT
) DEFAULT CHARSET=latin1;

INSERT INTO `m1` VALUES
 ('2011-02-19','Test-A',31,3)
,('2011-02-19','Test-B',34,3)
,('2011-02-19','Test-C',17,1)
,('2011-02-15','Test-A',48,4)
,('2011-02-15','Test-B',64,6)
,('2011-02-15','Test-C',55,5)
,('2011-02-11','Test-A',64,6)
,('2011-02-11','Test-B',53,5)
,('2011-02-11','Test-C',17,1)
,('2011-02-10','Test-A',12,1)
,('2011-02-10','Test-B',02,0)
,('2011-02-10','Test-C',54,5);

В этом запросе используется одна локальная переменная (@i).Введите в запросе имя_тесты ('Test-A') и дату ('2011-02-17'), показанные здесь как литералы.

SELECT o.tn AS `Test`
     , o.dt AS `Date`
     , SUM(CASE WHEN o.n = 1 THEN o.c3*1.00 ELSE NULL END) AS R
     , SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 2 THEN -1.00*o.c3 ELSE NULL END) AS R2
     , SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 3 THEN -1.00*o.c3 ELSE NULL END) AS R3
     , AVG(CASE WHEN o.n < 4 THEN c3*1.00 ELSE NULL END)-SUM(CASE WHEN n = 3 THEN c4*1.00 ELSE NULL END) AS R4
  FROM (
         SELECT @i := @i + 1 AS n
              , s.tn
              , s.dt
           -- , m.c1
              , m.c3
              , m.c4
           FROM (SELECT '2011-02-17' AS dt,_latin1'Test-A' AS tn, @i := 0) s
           JOIN m1 m
             ON m.c2 = s.tn AND m.c1 <= s.dt
          ORDER BY m.c1 DESC
          LIMIT 0,3
       ) o
 GROUP BY o.tn, o.dt
 HAVING SUM(1) >= 3

Вы можете запустить только внутренний запрос, раскомментироватьm.c1 из списка выбора, чтобы проверить возвращенные строки (1-й, 2-й и 3-й самые последние, до предоставленной даты.

Этот запрос возвращает значение R3, отличное от показанного в вопросе, но результатвозвращенный запросом представляется правильным результатом для данной формулы.

Кроме того, формула для R4 ссылается на 5 значений: avg (I, I1, I2, I3) -J3. Формула, используемая в запросеэффективно = avg (I1, I2, I3) -J3

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

SELECT o.tn AS `Test`
     , o.dt AS `Date`
     , SUM(CASE WHEN o.n = 1 THEN o.c3 ELSE NULL END) AS R
     , SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 2 THEN -1.00*o.c3 ELSE NULL END) AS R2
     , SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 3 THEN -1.00*o.c3 ELSE NULL END) AS R3
     , AVG(CASE WHEN o.n <= 3 THEN c3*1.00 ELSE NULL END)-SUM(CASE WHEN n = 3 THEN c4 ELSE NULL END) AS R4
  FROM (
         SELECT @i := CASE WHEN @prev_tn = m.c2 THEN @i + 1 ELSE 1 END AS n
              , @prev_dt := s.dt AS dt
              , @prev_tn := m.c2 AS tn
              , m.c1
              , m.c3
              , m.c4
           FROM (SELECT '2011-02-17' AS dt, @i := 0, @prev_tn := NULL) s
           JOIN m1 m
             ON m.c1 <= s.dt
          ORDER BY s.dt, m.c2, m.c1 DESC
       ) o
GROUP BY o.tn, o.dt
HAVING SUM(1) >= 3 

(Предложение HAVING гарантирует, что запросвозвращает результаты только в том случае, если для данного теста предшествует не менее трех строк, предшествующих данной дате.) Вот результат запроса для двух разных дат, 17-й и 20-й:

Test    Date        R   R2      R3      R4
------  ----------  --  ------  ------  -----
Test-A  2011-02-17  48  -52.96  -0.96   40.33
Test-B  2011-02-17  64  -38.28  12.72   39.67
Test-C  2011-02-17  55  -4.35   -41.35  37.00

Test    Date        R   R2      R3      R4
------  ----------  --  ------  ------  -----
Test-A  2011-02-20  31  -40.87  -56.87  41.67
Test-B  2011-02-20  34  -56.18  -45.18  45.33
Test-C  2011-02-20  17  -51.09  -13.09  28.67

(запрос будетбыть несколько более вовлеченным, чтобы получить результаты для более чем одной даты.)

Возможно, это не лучший способ решения проблемы, но я успешно использовал этот подход с MySQL.

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