SQL — использование результатов запроса в качестве основы для двух других запросов в одном операторе.

StackOverflow https://stackoverflow.com/questions/444673

Вопрос

Я делаю расчет вероятности.У меня есть запрос для расчета общего количества раз, когда происходит событие.Из этих событий я хочу получить количество раз, когда происходит дополнительное событие.Запрос на получение общего количества событий занимает 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 :-().Мне это нравится:делает то, что вам нужно, за один фрагмент, а затем уходит, с еще меньшими трудностями, чем временные таблицы.Прохладный.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top