2012-04-28 20 views
2

我有SQL查詢,我喜歡得到全部記錄。Mysql我一直得到總回報

我有一個僱主和600個僱主。

我需要得到所有的僱主,但由於某種原因,我的查詢返回僱主發佈的總工作。

請讓我知道我在這個查詢中出錯了。

SELECT count(c.id) as total 
FROM employer as c INNER JOIN job as j ON j.employerIDFK = c.id 
WHERE c.isActive=1 AND c.status=1 
AND j.isActive=1 
AND j.beenActive=1 
AND j.status=1 
AND DATE_ADD(j.createdAt, INTERVAL 30 DAY) > NOW() 
+1

有些東西會跳出我對這個查詢。 1)使用適當的連接。隱式連接導致大量問題(我懷疑它實際上涉及到這一點)。 2)預先計算NOW() - 30天,然後使用該值與j.createdAt進行比較。這樣,您可以避免全表掃描(如果j.createdAt被索引)。 – Corbin 2012-04-28 10:16:05

+0

我需要獲得仍然少於30天的完整工作清單。我不知道Precalculate NOW()是什麼意思? – Lalajee 2012-04-28 10:18:57

+0

由於NOW()的值不斷變化,因此MySQL必須爲每一行重新計算它的值。這意味着即使沒有DATE_ADD,也需要全表掃描。基本上,你有這個:'a + b Corbin 2012-04-28 10:21:20

回答

2
SELECT COUNT(DISTINCT c.id) AS total 
FROM employer c 
JOIN job j 
ON  j.employerIDFK = c.id 
WHERE c.isActive = 1 
     AND c.status = 1 
     AND j.isActive = 1 
     AND j.beenActive = 1 
     AND j.status = 1 
     AND j.createdAt >= NOW() - INTERVAL 30 DAY 

創建以下指標:

employer (isActive, status) 
job (employerFKID) 
job (isActive, beenActive, status, createdAt, employerFKID) 

的查詢更快的工作。

如果你不願意使用DISTINCT一些模糊的原因,你可以使用這個:

SELECT COUNT(c.id) AS total 
FROM employer c 
WHERE c.isActive = 1 
     AND c.status = 1 
     AND c.id IN 
     (
     SELECT employerIDFK 
     FROM job j 
     WHERE j.isActive = 1 
       AND j.beenActive = 1 
       AND j.status = 1 
       AND j.createdAt >= NOW() - INTERVAL 30 DAY 
     ) 

,然而,這可能是低效率的,因爲MySQL不能讓job引領這種查詢。

+0

這確實起作用。我現在只得到1條記錄,這是正確的。但是這可以不用DISTINCT – Lalajee 2012-04-28 11:34:35

+1

@Lalajee完成:你有什麼反對'DISTINCT'? – Quassnoi 2012-04-28 11:35:13

+0

在過去被告知要避免這種情況。 – Lalajee 2012-04-28 11:36:43

1

我懷疑「SELECT count(*)as total」是你的問題。您正在要求SQL計算返回的所有內容。注意你是什麼「選擇」 - 因爲這是唯一會返回給你的東西。

你沒有完全解釋你想在這裏實現什麼。 「我需要讓所有的僱主」含糊不清,難以理解。你想了解僱主的哪些數據?他們的ID?他們的總工作?

+0

這只是我分頁的總記錄。我需要要求系統返回在現場發佈崗位的僱主總數。 – Lalajee 2012-04-28 10:22:09

2

您的查詢應該爲所有僱主返回所有工作的計數,但有一些標準必須匹配才能顯示。如你所使用的,一個隱式連接是一個INNER JOIN。這要求所有標準匹配才能包含行。這意味着它只返回「isActive」,「beenActive」,「status = 1」,以及createdAt過去少於30天的職位,其中employeres是「isActive」和「status = 1」。檢查你的數據,看看這是你想要的。

SELECT c.id AS employerID, count(*) as total 
FROM employer as c, job as j 
WHERE c.isActive=1 AND c.status=1 
AND j.employerIDFK = c.id 
AND j.isActive=1 
AND j.beenActive=1 
AND j.status=1 
AND DATE_ADD(j.createdAt, INTERVAL 30 DAY) > NOW() 
GROUP BY c.id 

至於別人想說關於對createdAt過濾器,MySQL將首先評估NOW()(只有一次)。然後它爲每個createdAt日期添加30天,以查看它是否大於NOW()。 MySQL有時會自動優化它,它取決於你的版本和其他一些因素,但是一般來說,對每行的createdAt日期執行一個函數,將它與一個常量表達式進行比較是不好的,因爲MySQL不能使用索引createdAt列。

所以,你應該轉換:

AND DATE_ADD(j.createdAt, INTERVAL 30 DAY) > NOW() 

要這樣:

AND j.createdAt > DATE_ADD(NOW(), INTERVAL -30 DAY) 

這使得j.createdAt列作爲一個普通列,因此MySQL現在可以利用對列的任何索引查找日期在過去不到30天。

這相當於站在一個有100人的房間裏,並要求他們在他們的生日中增加30天,然後詢問誰的計算日期比今天更長。你只是讓100個人工作。相反,通過從今天的日期減去30天來預先計算標準,並簡單地詢問任何人的生日是否大於該日期。你只需要做一次計算,就可以讓這100人免去辛苦工作。

+0

謝謝您解決我的日期值。很抱歉,我的問題是,我需要在已發佈工作的僱主身上返回數字,而他們的工作時間不超過30天。但是我一直拿604條記錄,因爲我在我的僱主表中只有1個僱主,所以我只能得到1條記錄。 – Lalajee 2012-04-28 11:04:29

+0

我的僱主發佈了604份工作。 – Lalajee 2012-04-28 11:06:23

+0

@Lalajee,我更新了我的答案以提供一個類比。你的GROUP子句去哪了? – Ami 2012-04-28 11:06:25