SQL — использование результатов запроса в качестве основы для двух других запросов в одном операторе.
-
22-07-2019 - |
Вопрос
Я делаю расчет вероятности.У меня есть запрос для расчета общего количества раз, когда происходит событие.Из этих событий я хочу получить количество раз, когда происходит дополнительное событие.Запрос на получение общего количества событий занимает 25 строк, и я не хочу просто копировать и вставлять его дважды.
Я хочу сделать две вещи для этого запроса:вычислить количество строк в нем, и посчитать количество строк в результате запроса по этому запросу.На данный момент единственный способ, который я могу придумать, это сделать это (заменить @total@ сложным запросом для получения всех строк и @conditions@ менее сложными условиями, которым должны соответствовать строки из @total@). под-мероприятие):
SELECT (SELECT COUNT(*) FROM (@total@) AS t1 WHERE @conditions@) AS suboccurs,
COUNT(*) AS totaloccurs FROM (@total@) as t2
Как вы заметили, @total@ повторяется дважды.Есть ли способ обойти это?Есть ли лучший способ сделать то, что я пытаюсь сделать?
Еще раз подчеркну:@conditions@ действительно зависит от того, что возвращает @total@ (он делает такие вещи, как t1.foo = bar
).
Некоторые заключительные замечания:@total@ сам по себе занимает ~250 мс.Этот более сложный запрос занимает около 300 мс, поэтому postgres, скорее всего, сам выполняет некоторую оптимизацию.Тем не менее, запрос выглядит ужасно некрасиво, если @total@ вставлен буквально дважды.
Решение
SELECT COUNT(*) as totaloccurs, COUNT(@conditions@) as suboccurs
FROM (@total@ as t1)
Другие советы
Если ваш sql поддерживает факторинг подзапроса, то можно переписать его с помощью оператора WITH. Это позволяет использовать подзапросы более одного раза. Он создаст их в Oracle как встроенное представление или временную таблицу.
Вот надуманный пример.
WITH
x AS
(
SELECT this
FROM THERE
WHERE something is true
),
y AS
(
SELECT this-other-thing
FROM somewhereelse
WHERE something else is true
),
z AS
(
select count(*) k
FROM X
)
SELECT z.k, y.*, x.*
FROM x,y, z
WHERE X.abc = Y.abc
Поместите повторно используемый подзапрос во временную таблицу, затем выберите то, что вам нужно, из временной таблицы.
@EvilTeach:
Я не видел «с» (вероятно, не реализованного в Sybase :-().Мне это нравится:делает то, что вам нужно, за один фрагмент, а затем уходит, с еще меньшими трудностями, чем временные таблицы.Прохладный.