使用语句过滤而不使用from

时间:2014-08-27 12:58:27

标签: sql oracle count where

我想计算两个日期之间事件中展示的产品。我必须填写9列,每列都有其他产品类型。

我想问你是否有可能缩短这一说法。 下面的sql是第一个工作但不是有效的尝试。

with events(event_id, customer_id) as (
     select * from event
     where start_date >= :stare_date
     and end_date <= :end_date
),
select 
 (select count(*) from event_product where event_id in (select event_id from events where customer_id = customer.customer_id) and product_type = 'YLW') customer_ylw_products -- it works but its ugly and non effective
 -------
 -- repeat seven times for other type of products
 -------
 (select count(*) from event_product where event_id in (select event_id from events where customer_id = customer.customer_id) and product_type = 'RTL') customer_rtl_products
from customer
;

注意该行

(select event_id from events where customer_id = customer.customer_id)

重复约9次。

我一直试图通过添加以下内容来缩短这个:

with events(event_id, customer_id) as (
     select * from event
     where start_date >= :stare_date
     and end_date <= :end_date
),
**customer_events (event_id, customer_id) as (select * from events)**
select
(select count(*) from event_product where event_id in (select event_id from customer_events) and product_type = 'RTL') customer_rtl_products
from customers
where customer_events.customer_id = customer.customer_id -- doesnt works
having customer_events.customer_id = customer.customer_id -- doesnt works

2 个答案:

答案 0 :(得分:1)

为什么不使用案例表达式?

WITH
      events (event_id, customer_id)
      AS (
                  SELECT
                        *
                  FROM event
                  WHERE start_date >= :stare_date
                        AND end_date <= :end_date
            )
SELECT
      *
FROM customer
      LEFT JOIN (
                  SELECT
                        event_product.customer_id
                      , COUNT(CASE
                              WHEN event_product.product_type = 'YLW' THEN 1 END) AS count_YLW
                      , COUNT(CASE
                              WHEN event_product.product_type = 'RTL' THEN 1 END) AS count_RTL
                  FROM event_product
                        INNER JOIN events
                                    ON event_product.event_id = events.event_id
                  GROUP BY
                        event_product.customer_id
            ) ev_counts
                  ON customer.customer_id = ev_counts.customer_id
;

如果您愿意,也可以在没有CTE的情况下执行此操作,只需将您当前在CTE中使用的内容用作派生表,其中events现在放在内部联接中。


脚注select *只是方便我不知道要使用哪些字段,但应该指定它们。

答案 1 :(得分:1)

@Used_By_已经感谢您通过event_product和event之间的内部联接启发我,并且Event_product没有列customer_id所以我只是添加了它!

那是我的解决方案

with events(event_id, customer_id) as (
  select * from event
  where start_date >= :stare_date
  and end_date <= :end_date
),
product_events (customer_id, product_type) as (
  select event.customer_id, event_product.product_type 
  from events,event_product
  where event_product.event_id = event.event_id and event_product.product_type in (''product_types'')
)
select
  (select count(*) from product_events where customer_id = customer.customer_id and product_type = 'RTL') customer_rtl_products
from customers;

搜索中50行的性能从45秒增加到仅5行!

非常感谢你!