php
  • mysql
  • 2013-07-20 298 views 0 likes 
    0

    我正在開發一個租車網站。我有兩個表test_tbl_carstest_reservationsMysql搜索查詢

    我使用的搜索查詢(在"How do I approach this PHP/MYSQL query?"喬恩Kloske那兒剽竊):

    $sql = mysql_query("SELECT 
        test_tbl_cars.*, 
        SUM(rental_start_date <= '$ddate' AND rental_end_date >= '$adate') AS ExistingReservations 
        FROM test_tbl_cars 
        LEFT JOIN test_reservations USING (car_id) 
        GROUP BY car_id 
        HAVING ExistingReservations = 0"); 
    

    這給了我優秀的搜索結果,但test_tbl_cars表中包含許多汽車這在任何給定的搜索返回幾個同車的模型爲可用。

    如何過濾查詢返回,以便獲得每個模型的其中一個可用?

    +3

    使用'WHERE'子句過濾 –

    +1

    如何用GROUP BY car_id,car_model或任何你的模型字段命名替換GROUP BY car_id – user1914292

    +0

    你想要哪一個? – Strawberry

    回答

    0

    使用DISTICT條款

    $sql = mysql_query("SELECT 
    DISTINCT test_tbl_cars.model, test_tbl_cars.*, 
    SUM(rental_start_date <= '$ddate' AND rental_end_date >= '$adate') AS ExistingReservations 
    

    FROM test_tbl_cars LEFT JOIN test_reservations使用(car_id) GROUP BY car_id HAVING ExistingReservations = 0" );

    0

    噢,應該有我標籤的,我只看到了現在已經過了一年多了!你可能已經想出了現在如何工作,但爲了完整起見,我會採取一些措施,因爲大部分答案我都不認爲正在做你自己的工作想要。

    所以你遇到的問題是,在另一個問題,每個房間都有一個獨特的ID,這是獨特的房間人有興趣預訂。在這裏,您將可預訂物品的概念擴展到特定類別的物品池(在此情況下爲汽車模型)。

    可能有一種方法可以在沒有子查詢的情況下做到這一點,但迄今爲止,最簡單的方法是簡單地從我的其他答案中獲取最初的想法,並通過將其包含在另一個將模型分組爲模型的查詢中(正如你很快就會看到的那樣,我們可以免費得到一堆其他有用的東西)。

    那麼,首先讓通過獲取汽車的名單有衝突的保留計數(按照更新到我的其他答案)開始:

    (我會用你的查詢這些例子作爲出發點,但要注意,你真的應該在你的數據庫驅動程序爲你傳遞兩個參數提供最起碼的逃逸功能)

    SELECT car_id, model_id, SUM(IF(rental_id IS NULL, 0, rental_start_date <= '$ddate' AND rental_end_date >= '$adate')) AS ConflictingReservations 
    FROM test_tbl_cars 
    LEFT JOIN test_reservations USING (car_id) 
    GROUP BY car_id 
    

    這將每car_id返回一行給你的型號使用準備好的語句或,以及與您的日期範圍相沖突的預訂數量e指定(0或更多)。

    現在,在這個階段,如果我們詢問個別汽車(而不僅僅是汽車模型),我們可以通過「HAVING ConflictingReservations = 0 ORDER BY model_id」或其他來限制和排序結果。

    但是,如果我們想獲得〜模型的有效性名單〜,我們需要執行這些結果的另一組,以獲得最終的答案:

    SELECT model_id, COUNT(*) AS TotalCars, SUM(ConflictingReservations = 0) AS FreeCars, CAST(IFNULL(GROUP_CONCAT(IF(ConflictingReservations = 0, car_id, NULL) ORDER BY car_id ASC), '') AS CHAR) AS FreeCarsList 
    FROM (
        SELECT car_id, model_id, SUM(IF(rental_id IS NULL, 0, rental_start_date <= '$ddate' AND rental_end_date >= '$adate')) AS ConflictingReservations 
        FROM test_tbl_cars 
        LEFT JOIN test_reservations USING (car_id) 
        GROUP BY car_id 
    ) AS CarReservations 
    GROUP BY model_id 
    

    你會發現我們所有我們要做的是按照model_id對原始查詢進行分組,然後使用集合函數爲我們提供model_id,這是我們擁有這個模型的總車數,以及我們通過計算所有一輛車有零衝突預測,最後是一個可愛的一點SQL,返回一個逗號分隔的免費汽車的car_id列表(如果還需要!)

    關於性能的快速說明:所有左連接,分組和子查詢都可能會使該查詢的速度確實很慢。好消息是外部團隊應該只需要處理與你的車輛一樣多的行,所以它不應該緩慢,直到你最終擁有大量的汽車。然而,內部查詢連接兩個表(這可以通過索引相當快地完成),然後按整個集進行分組,每行執行一些功能。這可能會非常緩慢,特別是隨着預訂和汽車數量的增加。爲了減輕這一點,你可以使用內部查詢中的where子句並將其與適當的索引結合使用,以減少正在檢查的項目數量。還有其他一些技巧可以用來將開始日期和結束日期的比較移動到連接條件中,但這是另一天的主題:)

    最後,和往常一樣,如果邊緣情況不正確,錯誤,錯誤語法,不管 - 讓我知道,我會編輯更正!

    相關問題