从子选择

时间:2016-08-23 03:42:45

标签: mysql select count subquery

我试图在同一个查询中对多个表进行计数,其中2个计数的结果完全错误。我在此查询中使用了以下3个表:

CREATE TABLE `assignments` (
    `id` int(11) NOT NULL,
    `lead_id` int(11) NOT NULL,
    `buyer_id` int(11) NOT NULL,
    `refunded` int(11) NOT NULL DEFAULT '0',
    `date_assigned` int(11) NOT NULL,
    `date_refunded` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `leads` (
    `id` int(11) NOT NULL,
    `vertical_id` int(11) NOT NULL,
    `source_id` int(11) NOT NULL,
    `agent_id` varchar(255) DEFAULT NULL,
    `status_id` int(11) NOT NULL DEFAULT '0',
    `completeness` enum('Partial','Complete') DEFAULT NULL,
    `freshness` enum('New','Duplicate') NOT NULL,
    `date_created` int(11) NOT NULL,
    `date_updated` int(11) NOT NULL,
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `verticals` (
    `id` int(11) NOT NULL,
    `name` varchar(255) NOT NULL,
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

我想要做的是获取结果并将它们放入如下表格中:

Name        New Duplicate Partial Complete Total Assigned Refunded
Automotive  4   1         3       2        5     36       9
Education   16  7         9       14       23    36       9

前5个列号是正确的。问题是分配和退还的列号完全错误。这是我的疑问:

select v.*,
(select count(*) from `leads` where vertical_id=v.id and `freshness`='New' and `date_created` between 1470009600 and 1471923227) as `new`,
(select count(*) from `leads` where vertical_id=v.id and `freshness`='Duplicate' and `date_created` between 1470009600 and 1471923227) as `duplicate`,
(select count(*) from `leads` where vertical_id=v.id and `completeness`='Partial' and `date_created` between 1470009600 and 1471923227) as `partial`,
(select count(*) from `leads` where vertical_id=v.id and `completeness`='Complete' and `date_created` between 1470009600 and 1471923227) as `complete`,
(select count(*) from `leads` where vertical_id=v.id and `date_created` between 1470009600 and 1471923227) as `total`,
(select count(*) from `assignments` where lead_id=l.id and `refunded`=0) as `assigned`,
(select count(*) from `assignments` where lead_id=l.id and `refunded`=1) as `refunded`
from `verticals` as v
left join `leads` as l on (l.vertical_id = v.id)
where l.date_created between 1470009600 and 1471923227
group by v.id

如何在不使用子选择中的子选择的情况下纠正此问题(这会对性能造成影响)?

编辑:我相信我几乎有这个工作,但必须有更好的方法来编写此查询(同样,它似乎是将assignments分组为lead_id):

select o.*,
(select count(*) from `leads` where {$sql_column}=o.id and `freshness`='New' and `date_created` between {$date_from} and {$date_to}) as `new`,
(select count(*) from `leads` where {$sql_column}=o.id and `freshness`='Duplicate' and `date_created` between {$date_from} and {$date_to}) as `duplicate`,
(select count(*) from `leads` where {$sql_column}=o.id and `completeness`='Partial' and `date_created` between {$date_from} and {$date_to}) as `partial`,
(select count(*) from `leads` where {$sql_column}=o.id and `completeness`='Complete' and `date_created` between {$date_from} and {$date_to}) as `complete`,
(select count(*) from `leads` where {$sql_column}=o.id and `date_created` between {$date_from} and {$date_to}) as `total`,
(select count(*) from `assignments` where `lead_id` in 
    (select `id` from `leads` where {$sql_column}=o.id and `date_created` between {$date_from} and {$date_to}) and `refunded`=0) as `assigned`,
(select count(*) from `assignments` where `lead_id` in 
    (select `id` from `leads` where {$sql_column}=o.id and `date_created` between {$date_from} and {$date_to}) and `refunded`=1) as `refunded`
from {$sql_object} as o

2 个答案:

答案 0 :(得分:0)

select v.*,COUNT(CASE WHEN `freshness`='New' THEN freshness END) as new,COUNT(CASE WHEN `freshness`='Duplicate' THEN freshness END) as duplicate from `verticals` as v left join `leads` as l on (l.vertical_id = v.id) where l.date_created between 1470009600 and 1471923227 group by v.id

希望这会有所帮助。试试吧。

答案 1 :(得分:0)

鉴于此数据

/*
truncate table verticals;
INSERT INTO VERTICALS VALUES
(1,'Automotive'),(2,'Educational');

truncate table leads;
insert into leads values
(1,1,1,1,1,'Partial','New', 1470009600, 1470009600),
(2,2,1,1,1,'Partial','New', 1470009600, 1470009600),
(3,1,1,1,1,'Partial','Duplicate', 1470009600, 1470009600),
(4,2,1,1,1,'Partial','Duplicate', 1470009600, 1470009600),
(5,1,1,1,1,'Complete','New', 1470009600, 1470009600),
(6,2,1,1,1,'Complete','New', 1470009600, 1470009600),
(7,1,1,1,1,'Complete','Duplicate', 1470009600, 1470009600),
(8,2,1,1,1,'Complete','Duplicate', 1470009600, 1470009600),
(9,1,1,1,1,'Complete','New', 1470009600, 1470009600),
(10,1,1,1,1,'Complete','Duplicate', 1470009600, 1470009600);

truncate table assignments;
insert into assignments values
(1,1,1,0,1470009600, 1470009600),
(2,2,1,1,1470009600, 1470009600),
(3,3,1,0,1470009600, 1470009600),
(4,4,1,1,1470009600, 1470009600),
(5,5,1,1,1470009600, 1470009600);
*/

此查询

select v.*,
SUM(CASE WHEN L.`freshness`='New' THEN 1 ELSE 0 END) as `new`,
SUM(CASE WHEN L.`freshness`='Duplicate' THEN 1 ELSE 0 END) AS `duplicate`,
SUM(CASE WHEN L.`completeness`='Partial' THEN 1 ELSE 0 END)  as `partial`,
SUM(CASE WHEN L.`completeness`='Complete' THEN 1 ELSE 0 END)  as `complete`,
count(L.id)  as `total`,
SUM(CASE WHEN A.`refunded`=0 THEN 1 ELSE 0 END) as `assigned`,
SUM(CASE WHEN A.`refunded`=1 THEN 1 ELSE 0 END) as `refunded`
from `verticals` as v
left join `leads` as l on (l.vertical_id = v.id) AND  (l.date_created between 1470009600 and 1471923227)
LEFT JOIN ASSIGNMENTS A ON A.LEAD_ID = L.ID
group by v.id

结果

+----+-------------+------+-----------+---------+----------+-------+----------+----------+
| id | name        | new  | duplicate | partial | complete | total | assigned | refunded |
+----+-------------+------+-----------+---------+----------+-------+----------+----------+
|  1 | Automotive  |    3 |         3 |       2 |        4 |     6 |        2 |        1 |
|  2 | Educational |    2 |         2 |       2 |        2 |     4 |        0 |        2 |
+----+-------------+------+-----------+---------+----------+-------+----------+----------+