У меня есть запрос ниже, который дает мне общее количество часов в году, когда человек идет со скоростью более 2 миль в час. Объединено с запросом на общее количество записей (общее количество записанных часов). Оба являются в основном одним и тем же запросом, за исключением последнего предложения в первом. Проблема в том, что на выполнение этого запроса уходит добрых 30 секунд. Есть ли способ объединить два запроса, чтобы он работал быстрее, но получал похожие данные? Моя конечная цель - получить процент времени, в течение которого человек идет со скоростью более 2 миль в час.

SELECT COUNT(STARTING_HOUR) FROM SENSOR.SPEED
FULL OUTER JOIN ACCOUNT.ID
ON SENSOR.SPEED.Account_ID = ACCOUNT.ID.Account_ID
FULL OUTER JOIN ACCOUNT.NAME
ON ACCOUNT.ID.Account_ID = ACCOUNT.NAME.Account_ID
WHERE UPPER(NAME) LIKE '%Sarah%'
AND UPPER(NAME) LIKE '%Jones%'
AND STARTING_HOUR >= TO_DATE('2015-01-01T00:00:00', 'YYYY-MM-
DD"T"HH24:MI:SS')
AND STARTING_HOUR <= TO_DATE('2015-12-31T00:00:00', 'YYYY-MM-
DD"T"HH24:MI:SS')
AND Value > 2

UNION

SELECT COUNT(STARTING_HOUR) FROM SENSOR.SPEED
FULL OUTER JOIN ACCOUNT.ID
ON SENSOR.SPEED.Account_ID = ACCOUNT.ID.Account_ID
FULL OUTER JOIN ACCOUNT.NAME
ON ACCOUNT.ID.Account_ID = ACCOUNT.NAME.Account_ID
WHERE UPPER(NAME) LIKE '%Sarah%'
AND UPPER(NAME) LIKE '%Jones%'
AND STARTING_HOUR >= TO_DATE('2015-01-01T00:00:00', 'YYYY-MM-DD"T"HH24:MI:SS')
AND STARTING_HOUR <= TO_DATE('2015-12-31T00:00:00', 'YYYY-MM-DD"T"HH24:MI:SS')

Спасибо!

0
J. D. 25 Апр 2017 в 01:08

2 ответа

Лучший ответ

Во-первых, полное внешнее соединение совершенно излишне. Затем псевдонимы таблиц облегчают написание и чтение запроса. И тогда вы можете сделать арифметику, используя AVG():

SELECT AVG(CASE WHEN VALUE > 2 THEN 1.0 ELSE 0 END)
FROM SENSOR.SPEED s JOIN
     ACCOUNT.ID i
     ON s.Account_ID = i.Account_ID JOIN
     ACCOUNT.NAME n
     ON i.Account_ID = n.Account_ID
WHERE UPPER(NAME) LIKE '%Sarah%' AND
      UPPER(NAME) LIKE '%Jones%' AND
      STARTING_HOUR >= DATE '2015-01-01' AND
      STARTING_HOUR <= DATE '2015-12-31' ;

Я почти уверен, что предложения WHERE превращают все внешние объединения во внутренние. Возможно, вы хотите где-нибудь внешнее соединение, но не очевидно, что оно необходимо.

1
Gordon Linoff 24 Апр 2017 в 23:49
SELECT CASE
         WHEN COUNT(1) = 0   -- Handle division by zero
         THEN NULL
         ELSE COUNT( CASE WHEN value > 2 THEN 1 END )
              / COUNT( 1 )
       END AS Percentage
FROM   SENSOR.SPEED
       RIGHT OUTER JOIN ACCOUNT.NAME
       ON SENSOR.SPEED.Account_ID = ACCOUNT.NAME.Account_ID
WHERE  UPPER(NAME) LIKE '%SARAH%'
AND    UPPER(NAME) LIKE '%JONES%'
AND    STARTING_HOUR BETWEEN DATE '2015-01-01' AND DATE '2015-12-31'

Вам нужна таблица ACCOUNT.ID? Вместо этого, вы могли бы присоединиться напрямую от SENSOR.SPEED к ACCOUNT.NAME?

Я предполагаю, что NAME находится в ACCOUNT.NAME и с фильтром UPPER(NAME) это никогда не будет NULL, поэтому вы можете сделать RIGHT OUTER JOIN вместо {{X5 } } . В зависимости от того, в какой таблице находится столбец STARTING_HOUR, это может быть дополнительно упрощено до INNER JOIN.

1
MT0 24 Апр 2017 в 22:31