将子查询添加到查询中

时间:2013-01-28 17:30:49

标签: mysql

我不熟悉子查询,并认为在下列情况下我需要它们,但我不确定如何继续。

我有以下查询。现在,我有两件事需要添加到query =

  • 对于CA消费者,他们只能发生1次车祸(car_acc) 在其他州并没关系。
  • 在FL中,目前投保的MD,NH和WA可以是0(布尔值),而在其他状态下,它应该只有1。

    SELECT Count(*),
           Avg(sl.our_cost),
           Avg(sl.purchase_price)
    FROM   sold_leads AS sl
           INNER JOIN leads AS l
                   ON l.id = sl.lead_id
           INNER JOIN contacts AS c
                   ON c.lead_id = l.id
           INNER JOIN drivers AS d
                   ON d.lead_id = l.id
    WHERE  c.state IN( 'AK', 'AL', 'AR', 'AZ',
                       'CA', 'CO', 'CT', 'DC',
                       'DE', 'FL', 'GA', 'HI',
                       'IA', 'ID', 'IL', 'IN',
                       'KS', 'KY', 'LA', 'MD',
                       'ME', 'MI', 'MN', 'MO',
                       'MS', 'MT', 'NC', 'ND',
                       'NE', 'NH', 'NJ', 'NM',
                       'NV', 'NY', 'OH', 'OK',
                       'OR', 'PA', 'RI', 'SC',
                       'SD', 'TN', 'TX', 'UT',
                       'VA', 'VT', 'WA', 'WI',
                       'WV', 'WY' )
           AND l.leg = 0
           AND ( Datediff(CURRENT_DATE, d.date_of_birth) / 365 ) >= 50
           AND l.create_date >= '2012-1-1';  
    

如何将这些子查询添加到查询中? 有没有更好的方法来查找这些信息?

修改

我应该提一下,它应该是1'车祸'或'违规'。我有两个不同的车祸和违规表,因此对于CA居民,我只需要有1次意外或1次违规的人。

2 个答案:

答案 0 :(得分:1)

由于car_accidentsviolations的数据位于不同的表格中,因此您需要使用left join加入这些数据。

希望这是有道理的: - )

SELECT Count(*),
       Avg(sl.our_cost),
       Avg(sl.purchase_price)
FROM   sold_leads AS sl
       INNER JOIN leads AS l
               ON l.id = sl.lead_id
       INNER JOIN contacts AS c
               ON c.lead_id = l.id
       INNER JOIN drivers AS d
               ON d.lead_id = l.id
       LEFT JOIN 
  (SELECT ca1.driver_id, COUNT(*) AS cnt FROM car_accidents ca1 GROUP BY ca1.driver_id) ca 
               ON (c.state = 'CA' and ca.driver_id = d.id)
       LEFT JOIN 
  (SELECT v1.driver_id, COUNT(*) AS cnt FROM violations v1 GROUP BY v1.driver_id) v
               ON (c.state IN ('CA') and v.driver_id = d.id)
WHERE  c.state IN( 'AK', 'AL', 'AR', 'AZ','CA', 'CO', 'CT', 'DC',
                   'DE', 'FL', 'GA', 'HI','IA', 'ID', 'IL', 'IN',
                   'KS', 'KY', 'LA', 'MD','ME', 'MI', 'MN', 'MO',
                   'MS', 'MT', 'NC', 'ND','NE', 'NH', 'NJ', 'NM',
                   'NV', 'NY', 'OH', 'OK','OR', 'PA', 'RI', 'SC',
                   'SD', 'TN', 'TX', 'UT','VA', 'VT', 'WA', 'WI',
                   'WV', 'WY' )
       AND l.leg = 0
       AND ( Datediff(CURRENT_DATE, d.date_of_birth) / 365 ) >= 50
       AND l.create_date >= '2012-1-1'
       AND IFNULL(v.cnt,0) < 2 AND ifnull(ca.cnt.0) < 2
       AND (c.state IN ('FL','MD','NH','WA') OR c.IsInsured = 1) 

注意 将状态放在单独的表中会更有意义。 这样,您可以将条款和条件放在该表中,并在加入条件中使用它们。

Table state
-----------
id : varchar(2) primary key not null
country : varchar(45) not null
max_accidents : int null
max_violations : int null
must_be_insured : boolean not null

然后您可以将查询重写为:

SELECT Count(*),
       Avg(sl.our_cost),
       Avg(sl.purchase_price)
FROM   sold_leads AS sl
       INNER JOIN leads AS l
               ON l.id = sl.lead_id
       INNER JOIN contacts AS c
               ON c.lead_id = l.id
       INNER JOIN drivers AS d
               ON d.lead_id = l.id
       INNER JOIN state s ON (s.id = c.state)
       LEFT JOIN 
(SELECT ca1.driver_id, COUNT(*) AS cnt FROM car_accidents ca1 GROUP BY ca1.driver_id) ca 
           ON (s.max_accidents IS NOT NULL AND ca.driver_id = d.id)
   LEFT JOIN 
(SELECT v1.driver_id, COUNT(*) AS cnt FROM violations v1 GROUP BY v1.driver_id) v
           ON (s.max_violations IS NOT NULL AND v.driver_id = d.id)
       AND l.leg = 0
       AND (Datediff(CURRENT_DATE, d.date_of_birth) / 365.25 ) >= 50
       AND l.create_date >= '2012-1-1'; 
       AND IFNULL(v.cnt,0) < 2 AND ifnull(ca.cnt.0) < 2
       AND (s.must_be_insured = 0 OR c.IsInsured = 1)

答案 1 :(得分:0)

我知道它与子查询不同,但我经常用CASE语句解决这个“子条件”问题。您可以在WHERE子句的末尾添加一个:

WHERE c.state IN (...)
    AND l.leg = 0
    AND ( Datediff(CURRENT_DATE, d.date_of_birth) / 365 ) >= 50
    AND l.create_date >= '2012-1-1'
    AND CASE 
        # Identify cases where record should be excluded
        WHEN c.state = 'CA' AND c.car_acc > 1   THEN 0
        WHEN c.state NOT IN ('FL', 'MD', 'NH', 'WA') AND c.currently_insured = 1   THEN 0
        ELSE 1
    END = 1

警告:与其他过滤方法相比,我不知道这会如何影响性能。