嘗試
SELECT ag.AgeGroup_Des, count(1)
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
INNER JOIN tblAgeGroup ag ON ag.minAge <= m.Age and ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30'
GROUP BY ag.AgeGroup_Des
然而,使用間隔,因爲我們在這裏做的tblAgeGroup加入時,它來測試我們得到正確的行數是很重要的。
所以我會運行下面的查詢,並驗證他們確實做返回相同的行數:
SELECT COUNT(1)
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
--INNER JOIN tblAgeGroup ag ON ag.minAge <= m.Age and ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30'
和
SELECT COUNT(1)
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
INNER JOIN tblAgeGroup ag ON ag.minAge <= m.Age and ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30'
有跡象表明,我想起兩兩件事,在這裏使用間隔時可能會出錯。
首先;如果間隔沒有唯一定義,則每個成員都會返回幾次。 如考慮含 ... ,MINAGE = 15 ,MAXAGE = 35 ... 和另一個條目tblAgeGroup: ... ,MINAGE = 20 ,MAXAGE = 25 ...
與21年齡將因此在這兩個區間得到恢復,從而在數量製造通貨膨脹的成員。
其次;如果Age未在tblMembers中定義,則該行將被排除,但這可能是有意的,因爲我們正在使用內部聯接。 你可以解決這個問題,有以下幾點:
SELECT ISNULL(ag.AgeGroup_Des, 'No group found') as AgeGroup_Des,
COUNT(1) as "AMT users"
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
LEFT JOIN tblAgeGroup ag ON ag.minAge <= m.Age and ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30'
GROUP BY ISNULL(ag.AgeGroup_Des, 'No group found')
ORDER BY 1
編輯: 增加了SQLFiddle測試: http://sqlfiddle.com/#!6/137b8/5
查詢的小提琴是:
體形:
CREATE TABLE tblMembers
(
Member_ID int,
DOB date,
Age int
);
CREATE TABLE tblAgeGroup
(
[AgeGroup Id] int,
AgeGroup_Des varchar(16),
minAge int,
maxAge int,
meanAge float
);
CREATE TABLE tblLog
(
Member_id int,
AccessDate date
);
INSERT INTO tblMembers
(Member_ID, DOB, Age)
SELECT 1, '1991-03-22', 23
UNION ALL
SELECT 2, '2000-03-22', 14
UNION ALL
SELECT 3, '1981-03-22', 33
UNION ALL
SELECT 4, null, null;
INSERT INTO tblAgeGroup
([AgeGroup Id], AgeGroup_Des, minAge, maxAge, meanAge)
SELECT 1, '15-25', 15, 25, null
UNION ALL
SELECT 2, '10-15', 10, 15, null
UNION ALL
SELECT 3, '25-55', 25, 55, null;
INSERT INTO tblLog
(Member_id, AccessDate)
SELECT 1, GETDATE()
UNION ALL
SELECT 2, GETDATE()
UNION ALL
SELECT 1, '2014-04-02'
UNION ALL
SELECT 2, '2014-04-03'
UNION ALL
SELECT 2, '2014-04-03'
UNION ALL
SELECT 3, '2014-04-03'
UNION ALL
SELECT 4, '2014-04-03';
查詢:
-- First query: (exludes member 4, since no DOB is registered:
SELECT ag.AgeGroup_Des, COUNT(1)
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
INNER JOIN tblAgeGroup ag ON ag.minAge <= m.Age and ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30'
GROUP BY ag.AgeGroup_Des;
-- To validate that the counts are the same:
SELECT COUNT(1)
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
--INNER JOIN tblAgeGroup ag ON ag.minAge <= m.Age AND ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30';
-- Second validation:
-- Notice: this does return one less row, since we are using inner join,
-- and thus ommitting member 4
SELECT COUNT(1)
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
INNER JOIN tblAgeGroup ag ON ag.minAge <= m.Age AND ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30';
-- Last query, which includes members with no DOB registered,
-- as well as members that does not fall into any group:
SELECT ISNULL(ag.AgeGroup_Des, 'No group found') as AgeGroup_Des,
COUNT(1) as "AMT users"
FROM tblLog l
INNER JOIN tblMembers m ON m.Member_Id = l.Member_Id
LEFT JOIN tblAgeGroup ag ON ag.minAge <= m.Age AND ag.maxAge > m.Age
WHERE AccessDate >= '2014-04-01'
AND AccessDate <= '2014-04-30'
GRUOP BY ISNULL(ag.AgeGroup_Des, 'No group found')
ORDER BY 1;
2014年5月14日:編輯:
我在您的意見看,你還需要爲空組計數。爲了做到這一點,我已經「倒置」了from子句,以便我們從tblAgeGroup中選擇所有,然後左加入其他表。
此外,我認爲你需要一些日誌條目,但在閱讀評論後,我看到你要求不同的用戶。我已經相應地更改了查詢。
select
ag.AgeGroup_Des
, count(l.Member_ID) as [AMT Log entries]
, count(distinct l.Member_ID) as [AMT distinct members]
from tblAgeGroup ag
left join tblMembers m on ag.minAge <= m.Age and ag.maxAge > m.Age
left join tblLog l on l.Member_id = m.Member_ID
group by isnull(ag.AgeGroup_Des, 'No group found')
order by 1
;
返回
AgeGroup_Des AMT Log entries AMT distinct members
10-15 3 1
15-25 2 1
25-55 1 1
55-65 0 0
然而,這種方法確實會忽略不具有DOB /年齡登記的每一個成員。 如果我們要包括這些藏漢,我們需要編輯查詢到完全外部聯接:
select
isnull(ag.AgeGroup_Des, 'No group found') as AgeGroup_Des
, count(l.Member_ID) as [AMT Log entries]
, count(distinct l.Member_ID) as [AMT distinct members]
from tblAgeGroup ag
full outer join tblMembers m on ag.minAge <= m.Age and ag.maxAge > m.Age
full outer join tblLog l on l.Member_id = m.Member_ID
group by isnull(ag.AgeGroup_Des, 'No group found')
order by 1
;
返回
AgeGroup_Des AMT Log entries AMT distinct members
10-15 3 1
15-25 2 1
25-55 1 1
55-65 0 0
No group found 1 1
見更新小提琴這裏:http://sqlfiddle.com/#!6/d8733/5
您使用的是哪種數據庫平臺? MySQL或SQL Server? –
當您運行該查詢時會發生什麼? –
@PatrickHofman我正在使用MSSQL –