2014-02-24 23 views
0

我試圖拉一些星期超過一週,並且我建立的查詢得到的數據,但是可怕的很慢。拉動趨勢數據WeeK過去一週

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| 

被refrenced表是:

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)); 

有沒有更好的方式來獲得這些數據?

回答

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條款。

+0

我喜歡這個(不需要子查詢),但我認爲它應該是'> ='而不是'>'。 – PlantTheIdea

+0

@PlantTheIdea你可能對'> ='和'>'是正確的,它將取決於OP是否想要在一週前包含或排除從NOW()到精確的第二秒。 –

+0

我喜歡它看起來很乾淨,但是我得到這個錯誤:錯誤代碼:1064 您的SQL語法錯誤;檢查對應於你的MySQL服務器版本正確的語法使用近 'CASE AS LAST_WEEK_COUNT), SUM(CASE WHEN app_d' 手冊在第7行 –

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)) 
    ) 
+0

年度周是1周前還是2周前?你認爲有多少記錄符合該要求? – PlantTheIdea

+0

是的,看到編輯。 – Rahul

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標準。

只是一個想法,我的頭頂。