2013-09-30 17 views
6

我有以下架構表:查詢到任何結果,只有當ORDER BY新增

people_stages

id | person_id | stage_id | created 
1  | 1   | 1   | 2013-09-01 00:00:00 
2  | 1   | 2   | 2013-09-02 00:00:00 
3  | 1   | 3   | 2013-09-03 00:00:00 

我創建了下面的查詢選擇由人分組的最近階段:

SELECT * 
FROM people Person 
LEFT JOIN people_stages PersonStage ON PersonStage.person_id = Person.id 
WHERE PersonStage.created = (SELECT MAX(people_stages.created) FROM people_stages GROUP BY person_id HAVING person_id = PersonStage.person_id); 

它工作正常,但是,如果我嘗試爲了通過場中Person表:

SELECT * 
FROM people Person 
LEFT JOIN people_stages PersonStage ON PersonStage.person_id = Person.id 
WHERE PersonStage.created = (SELECT MAX(people_stages.created) FROM people_stages GROUP BY person_id HAVING person_id = PersonStage.person_id) 
ORDER BY Person.last_name; 

它返回0結果。

任何人都可以提供一些見解嗎?

謝謝!

編輯:的people

+----------------------------+--------------------------------------------------------------+------+-----+---------+----------------+ 
| Field      | Type               | Null | Key | Default | Extra   | 
+----------------------------+--------------------------------------------------------------+------+-----+---------+----------------+ 
| id       | bigint(20)             | NO | PRI | NULL | auto_increment | 
| internal_id    | varchar(50)             | NO | MUL | NULL |    | 
| public_id     | varchar(30)             | NO |  | NULL |    | 
| counselor_id    | bigint(20)             | NO |  | NULL |    | 
| term_id     | int(11)              | NO | MUL | NULL |    | 
| program_id     | int(11)              | NO |  | NULL |    | 
| person_type_id    | int(11)              | NO | MUL | NULL |    | 
| first_name     | varchar(100)             | NO |  | NULL |    | 
| middle_name    | varchar(100)             | NO |  | NULL |    | 
| last_name     | varchar(100)             | NO |  | NULL |    | 
| photo_url     | varchar(255)             | NO |  | NULL |    | 
| gender      | enum('m','f','u')           | NO |  | NULL |    | 
| date_of_birth    | date               | NO |  | NULL |    | 
| address     | varchar(255)             | NO |  | NULL |    | 
| address_apt    | varchar(100)             | NO |  | NULL |    | 
| address_city    | varchar(100)             | NO |  | NULL |    | 
| address_state    | varchar(100)             | NO |  | NULL |    | 
| address_state_intl   | varchar(255)             | NO |  | NULL |    | 
| address_zip    | varchar(25)             | NO |  | NULL |    | 
| address_country   | varchar(100)             | NO |  | NULL |    | 
| address_verified   | tinyint(1)             | NO |  | NULL |    | 
| address_latitude   | varchar(100)             | NO |  | NULL |    | 
| address_longitude   | varchar(100)             | NO |  | NULL |    | 
| address_position   | point              | NO | MUL | NULL |    | 
| address_distance   | smallint(6)             | NO |  | NULL |    | 
| social_facebook   | mediumtext             | NO |  | NULL |    | 
| social_twitter    | varchar(255)             | NO |  | NULL |    | 
| social_instagram   | varchar(255)             | NO |  | NULL |    | 
| phone_cell     | varchar(25)             | NO |  | NULL |    | 
| phone_cell_clean   | varchar(25)             | YES |  | NULL |    | 
| phone_work     | varchar(25)             | NO |  | NULL |    | 
| phone_work_clean   | varchar(25)             | NO |  | NULL |    | 
| permission_to_text   | tinyint(1)             | NO |  | NULL |    | 
| permission_to_text_confirm | tinyint(1)             | NO |  | NULL |    | 
| phone_home     | varchar(25)             | NO |  | NULL |    | 
| phone_home_clean   | varchar(25)             | YES |  | NULL |    | 
| email_address    | varchar(255)             | NO |  | NULL |    | 
| permission_to_email  | tinyint(1)             | NO |  | NULL |    | 
| preferred_contact   | enum('phone_home','phone_cell','text_cell','email','postal') | NO |  | NULL |    | 
| parent_first_name   | varchar(100)             | NO |  | NULL |    | 
| parent_last_name   | varchar(100)             | NO |  | NULL |    | 
| parent_email    | varchar(255)             | NO |  | NULL |    | 
| hs_name     | varchar(255)             | NO |  | NULL |    | 
| hs_homeschooled   | tinyint(1)             | NO |  | NULL |    | 
| hs_ceeb_id     | varchar(100)             | NO |  | NULL |    | 
| hs_grad_year    | varchar(4)             | NO |  | NULL |    | 
| coll_name     | varchar(255)             | NO |  | NULL |    | 
| coll_ceeb_id    | varchar(100)             | NO |  | NULL |    | 
| coll_major     | varchar(255)             | NO |  | NULL |    | 
| coll_year     | varchar(20)             | NO |  | NULL |    | 
| counselor_read    | tinyint(1)             | NO |  | NULL |    | 
| source      | varchar(100)             | NO |  | NULL |    | 
| entry_method    | varchar(100)             | NO |  | NULL |    | 
| erp_processed    | tinyint(1)             | NO |  | NULL |    | 
| created     | datetime              | NO |  | NULL |    | 
| modified     | datetime              | NO |  | NULL |    | 
+----------------------------+--------------------------------------------------------------+------+-----+---------+----------------+ 
+2

引起你能提供tblPeople的表結構的一個行爲PLZ ? –

+0

你確定你有這個字段在tablev Person.last_name –

+0

你試過沒有表別名? –

回答

3

這似乎是在MySQL中的錯誤,對此我有filed a report結構。我把它縮小到下面的測試情況下,人們將期望返回單個記錄(但事實並非如此):

CREATE TABLE t (x INT NULL); -- table with nullable column 
INSERT INTO t VALUES (0); -- but non null data 

SELECT a.x     -- select our nullable column 
FROM  t a, (SELECT NULL) b -- joining it with anything at all 

WHERE EXISTS (   -- but filter on a subquery 
      SELECT * 
      FROM (SELECT NULL) c -- doesn't really matter what 
      HAVING a.x IS NOT NULL -- provided there is some correlated condition 
            -- on our nullable column in the HAVING clause 
     ) 

ORDER BY RAND()    -- then perform a filesort on the outer query 

看到它的sqlfiddle

在你的情況,你可以做很多事情來解決這個問題:

  1. 通過改寫爲避免相關子查詢聯接:

    SELECT * 
    FROM  people AS p LEFT JOIN (people_stages AS s NATURAL JOIN (
          SELECT person_id, MAX(created) created 
          FROM  people_stages 
          GROUP BY person_id 
         ) t) ON s.person_id = p.id 
    ORDER BY p.last_name 
    
  2. 如果你想保留相關子查詢(通常可能會導致性能較差但通常更容易理解),請使用WHERE而不是HAVING

    SELECT * 
    FROM  people AS p LEFT JOIN people_stages AS s ON s.person_id = p.id 
    WHERE s.created = (
          SELECT MAX(created) 
          FROM people_stages 
          WHERE person_id = s.person_id 
         ) 
    ORDER BY p.last_name 
    
  3. 如果您無法更改查詢,你會發現,使people_stages.person_id列非空的會得到解決的問題:

    ALTER TABLE people_stages MODIFY person_id BIGINT UNSIGNED NOT NULL 
    

    似乎有對列的索引(這將需要實現一個外鍵約束)也可以幫助:

    ALTER TABLE people_stages ADD FOREIGN KEY (person_id) REFERENCES people (id) 
    
  4. 另外一個可以從選擇列表中刪除people_stages.person_id,或調整數據模型/索引/查詢策略,以避免文件排序(可能是不實際在這案例,但我在這裏提到他們的完整性)。

+0

錯誤在哪裏? EXISTS(SELECT * FROM(SELECT NULL)c HAVING a.x IS NOT NULL)永遠不會存在。或者錯過了我的觀點? –

+0

@LorenzMeyer:包含單個「NULL」字段的記錄與完全不記錄相同。 – eggyal

+0

謝謝!這讓我瘋狂。 – Pete

0

檢查你是不是在你的服務器運行的空間......是的,聽起來很奇怪,但像描述可以通過

相關問題