我试图在一周内扣除一些金额,我建立的查询得到的数据,但是非常慢。
SELECT app_client_id
, (SELECT COUNT(b.app_id) FROM `li_appointments` AS b
WHERE YEARWEEK(b.app_datetime) = YEARWEEK(DATE_ADD(NOW(),INTERVAL -1 WEEK))
AND b.app_client_id = a.app_client_id)
, (SELECT COUNT(b.app_id) FROM `li_appointments` AS b
WHERE YEARWEEK(b.app_datetime) = YEARWEEK(DATE_ADD(NOW(),INTERVAL -2 WEEK))
AND b.app_client_id = a.app_client_id)
FROM `li_appointments` AS a
EXPLAIN给了我这个:
|id||select_type ||table||type ||possible_keys||key ||key_len||ref||rows ||Extra |
|1 ||PRIMARY ||a ||index|\N |Extra||18 |\N |61901||Using index|
|3 ||DEPENDENT SUBQUERY||b ||index|\N |Extra||18 |\N |61901||Using where; Using index|
|2 ||DEPENDENT SUBQUERY||b ||index|\N |Extra||18 |\N |61901||Using where; Using index|
正在引用的表是:
create table `li_appointments` (
`app_id` int (11),
`app_datetime` datetime ,
`app_facility` varchar (600),
`app_department` varchar (600),
`app_address` varchar (600),
`app_language` varchar (600),
`app_requesting_person` varchar (600),
`app_service_provider` varchar (600),
`app_client_id` int (11),
`app_client_other` varchar (600),
`app_medicaid_status` int (11),
`app_health_program` varchar (150),
`les_name` varchar (500),
`les_dob` varchar (75),
`les_medicaid_id` varchar (500),
`billing_total_time` time ,
`billing_workorder_received` int (11),
`billing_admin_fee` float ,
`billing_notes` varchar (3000),
`app_notes` varchar (3000),
`created_by` varchar (300),
`created_on` datetime ,
`modified_by` varchar (300),
`modified_on` datetime ,
`wo_entered_by` varchar (300),
`app_callback_num` varchar (135),
`terp_id` varchar (135),
`app_covered_by` varchar (135),
`covered_on` datetime ,
`uofu_csn` varchar (135));
有没有更好的方法来获取这些数据?
答案 0 :(得分:1)
这可能很慢,因为你所有的WHERE子句都使用像YEARWEEK(b.app_datetime)
这样的东西来阻止使用索引以及你正在使用子选择这一事实。
我真的不明白你为什么要使用子选择。一个简单的案例陈述应该消除这种需要:
SELECT
app_client_id,
SUM(
CASE
WHEN app_datetime > DATE_ADD(NOW(),INTERVAL -1 WEEK) THEN 1
ELSE 0
END
) AS last_week_count,
SUM(
CASE
WHEN app_datetime > DATE_ADD(NOW(),INTERVAL -1 WEEK) THEN 0
WHEN app_datetime > DATE_ADD(NOW(),INTERVAL -2 WEEK) THEN 1
ELSE 0
END
) AS two_weeks_ago_count
FROM `li_appointments`
GROUP BY app_client_id
确保您在app_client_id
上有索引。
还应该注意,这将提供每周滚动数据集。在您的原始问题中,您使用的YEARWEEK()
可能实际上一次提供超过一周的数据。例如,假设它是星期三,我想计算YEARWEEK()
等于上周三的所有项目。这实际上会匹配SUN / MON到前一周的SAT / SUN的所有项目(周开始和结束,具体取决于MySQL运行的模式与周编号有关)。
如果这实际上是你想要的,那就更容易实现:
SELECT
app_client_id,
YEARWEEK(app_datetime) AS year_week,
SUM(1) as weekly_count
FROM `li_appointments`
GROUP BY `app_client_id`, `year_week`
HAVING `year_week` < YEARWEEK(NOW())
ORDER BY `year_week` DESC
LIMIT 2
这将为您提供过去两周的数据,但不是当前周。如果您想要当前周(可能长达6天,长度为23:59:59),只需删除HAVING
条款。
答案 1 :(得分:0)
将子查询更改为如下所示加入,看看它是否提高了性能
SELECT
a.app_client_id,
COUNT(b.app_id) as appid_count
from app_client_id a join
li_appointments b on b.app_client_id = a.app_client_id
where
YEARWEEK(b.app_datetime) in
(
(YEARWEEK(DATE_ADD(NOW(),INTERVAL -1 WEEK)),
(YEARWEEK(DATE_ADD(NOW(),INTERVAL -2 WEEK))
)
答案 2 :(得分:0)
您可能想尝试使用UNION ALL
设置的子查询:
SELECT app_client_id
,SUM(app_id_count_1_week) AS app_id_count_1_week
,SUM(app_id_count_2_weeks) AS app_id_count_2_weeks
FROM (
SELECT app_client_id
,COUNT(app_id) AS app_id_count_1_week
,CAST(0 AS INTEGER) AS app_id_count_2_weeks
FROM li_appointments
WHERE b.app_datetime >= CURRENT_DATE - INTERVAL '7' DAY
GROUP BY app_client_id
UNION ALL
SELECT app_client_id
,CAST(0 AS INTEGER) AS app_id_count_1_week
,COUNT(app_id) AS app_id_count_2_weeks
FROM li_appointments
WHERE b.app_datetime >= CURRENT_DATE - INTERVAL '14' DAY
GROUP BY app_client_id
) AS Both_Counts
GROUP BY app_client_id
这将根据需要单独进行聚合,UNION
结果,然后顶层的SUM
将添加实际的COUNT
和0.语法的更改是使WHERE
子句符合ANSI标准。
只是一个想法。