2013-03-08 178 views
2

我有查询有子查询作为字段列,但我想在其他地方使用此字段列。使用子查询作为字段列

SELECT c.country_code             AS 
     country_code, 
     c.dial_code              AS 
     dial_code, 
     (SELECT r.destination 
     FROM region r 
     WHERE r.country_code = c.country_code 
       AND r.dial_code = c.dial_code)       AS 
     destination, 
     c.start_time, 
     c.duration, 
     c.call_type, 
     c.customer_prefix             AS 
     customer_prefix, 
     c.vendor_prefix             AS 
     vendor_prefix, 
     (SELECT Round(r.rate, 3) 
     FROM rate r 
       INNER JOIN region re 
         ON r.region_id = re.id 
       INNER JOIN account_prefix ap 
         ON r.account_prefix_id = ap.id 
     WHERE re.country_code = c.country_code 
       AND re.dial_code = c.dial_code 
       AND ap.prefix = c.customer_prefix 
       AND ap.prefix_type = 0)         AS 
     **customer_rate**, 
     (SELECT Round(r.rate, 3) 
     FROM rate r 
       INNER JOIN region re 
         ON r.region_id = re.id 
       INNER JOIN account_prefix ap 
         ON r.account_prefix_id = ap.id 
     WHERE re.country_code = c.country_code 
       AND re.dial_code = c.dial_code 
       AND ap.prefix = c.vendor_prefix 
       AND ap.prefix_type = 1)         AS 
     **vendor_rate**, 
     (SELECT Round(r.rate, 3) 
     FROM rate r 
       INNER JOIN region re 
         ON r.region_id = re.id 
       INNER JOIN account_prefix ap 
         ON r.account_prefix_id = ap.id 
     WHERE re.country_code = c.country_code 
       AND re.dial_code = c.dial_code 
       AND ap.prefix = c.customer_prefix 
       AND ap.prefix_type = 0) - (SELECT Round(r.rate, 3) 
              FROM rate r 
               INNER JOIN region re 
                 ON r.region_id = re.id 
               INNER JOIN account_prefix ap 
                 ON r.account_prefix_id 
                  = ap.id 
              WHERE 
     re.country_code = c.country_code 
     AND re.dial_code = c.dial_code 
     AND ap.prefix = c.vendor_prefix 
     AND ap.prefix_type = 1) AS **unit_profit**, 
     unit_profit * duration 
FROM cdr c 
LIMIT 100; 

正如你所看到的,我想要使用unit_profit,customer_rate和vendor_rate。如何实现它?

编辑:

任何教程显示加入视图?

+0

您不能直接使用在同一个SELECT列表中定义的别名。您将需要使用外部查询,或者(如果您的RDBMS支持它)CTE。 – 2013-03-08 02:02:37

+0

请详细说明外部查询。什么是CTE?我正在使用mysql数据库。 – peterwkc 2013-03-08 02:35:16

+0

Erwin Brandstetter的答案给出了一个外部查询的例子(额外的SELECT FROM所有内部查询,CTE代表* Common Tables Expressions *(我正在考虑'WITH'),但显然MySQL不支持它 – 2013-03-08 02:41:13

回答

2

你需要做的是采取所有那些flieds内部完成子查询,并建立与CDR表的连接。

这将大大提高查询和响应时间的性能。你现在正在做的是在CDR上为每条记录执行3个查询。如果这张表(CDR)只有几条记录是好的,但是如果不是这样可能会消耗大量的处理器,内存和磁盘I/O。

The trick to do the "join" and show the info in the same format is to join 3 times the same subquery but with a different alias. 

select c.country_code, customer_rate_table.customer_rate 
from CDR c 
left outer join on (SELECT Round(r.rate, 3) customer_rate , re.country_code, 
         re.dial_code, re.dial_code, ap.prefix 
       FROM rate r 
       INNER JOIN region re 
         ON r.region_id = re.id 
       INNER JOIN account_prefix ap 
         ON r.account_prefix_id = ap.id 
       WHERE ap.prefix_type = 1 

) customer_rate_table 
ON customer_rate.country_code = c.country_code 
AND customer_rate.dial_code = c.dial_code 
AND customer_rate.prefix = c. customer_prefix 
left outer join on ({Same as above but with the right fields}) vendor_rate_table 
ON vendor_rate_table.country_code = c.country_code 
AND vendor_rate_table.dial_code = c.dial_code 
AND vendor_rate_table.prefix = c.vendor_prefix 

再下表...

此代码是不完整的,但我想给你需要做什么解释。

谢谢!

@leo

+0

这种技术叫做什么?通常,我们加入使用PK和FK的关系,但这次我们使用表来加入。它在mysql上不可执行。 – peterwkc 2013-03-08 02:41:38

+0

这基本上是一个连接,但不是使用表使用与他们自己的PKs专用视图 – lemil77 2013-03-08 02:48:08

+0

加入使用视图而不是表。官方名称是什么? – peterwkc 2013-03-08 03:01:44

1

相关的子查询就像你在你的查询中一般在性能方面很糟糕。由于您只能检索100行,因此应该不会太差,但如果您希望得到更快,则必须重新编写查询。

手头的问题可以很容易地被固定:

SELECT *, unit_profit * duration AS my_calc 
FROM (
    -- your query here 
    -- just without "unit_profit * duration" 
    -- and maybe without redundant column aliases 
    ) AS sub 
+0

你能提供一个完整的例子? – peterwkc 2013-03-08 02:34:30

+0

@peterwkc:这是一个完整的例子,按照说明插入你的查询作为子查询 – 2013-03-08 03:23:41

+0

我认为你的方法和lemil77是一样的,但区别在于加入语句和从子句查看 – peterwkc 2013-03-08 03:48:29