我不熟悉子查询,并认为在下列情况下我需要它们,但我不确定如何继续。
我有以下查询。现在,我有两件事需要添加到query =
在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次违规的人。
答案 0 :(得分:1)
由于car_accidents
,violations
的数据位于不同的表格中,因此您需要使用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
警告:与其他过滤方法相比,我不知道这会如何影响性能。