2014-01-30 97 views
1

對不起,標題。我現在不能提供任何有意義的東西,但如果您提出任何建議,我會更新它。令人難以置信的SQL難題

好的,這個問題一直困擾着我好幾天了,並且讓我發瘋。

我有一個數據庫,保持教育相關的過濾器。

table: FILTERS 

filterid filtertype value 
1  school  MIT 
1  school  UT 
1  school  Lund 
1  major  econ 
1  major  civil 
1  graduate 1 
2  school  Harvard 

所以在這裏我有兩個過濾器定義,1和2的教育記錄通過過濾器1如果學校(MIT,UT或隆德)之一,主要是(經濟或民間)之一,是一個研究生課程。 通過過濾器2,一個教育記錄需要哈佛剛剛作爲學校。

我有另一張表,爲用戶保存教育記錄。用戶可以有幾個教育記錄(例如,一個是她的本科學業,一個研究生)

table: EDUCATION 
educid uid school major graduate 
1  1  MIT  econ 1 
2  1  Lund  cs  0 

所以人1有兩個教育記錄。 在這裏,教育記錄1通過過濾器1,因爲學校(MIT)屬於{MIT,UT,Lund),主要(econ)屬於{econ,civil}組並且是一個研究生課程。然而,教育記錄1沒有通過過濾器2,因爲學校是MIT,而不是哈佛。

教育記錄2沒有通過過濾器1,因爲主要(cs)不在{econ,civil},並且它不通過過濾器2,因爲學校是隆德而不是哈佛。

1人未通過過濾器1,如果沒有她的教育記錄經過過濾器1 因此,1個人經過過濾器1(因爲她的第一個教育記錄通過過濾器1),但不通過過濾器2,因爲沒有的hiher的教育記錄通過過濾器2.

我的目標是選擇人1不通過的過濾器filterid。

這就是我來這麼遠:

SELECT filterid FROM filters 
LEFT JOIN education ON education.uid=1 AND (
(filtertype='school' AND filters.value=education.school) OR 
(filtertype='major' AND filters.value=education.major) OR 
(filtertype='graduate' AND filters.value=education.graduate) 
) 
GROUP BY filterid 
HAVING (SUM(educid IS NULL)>0) 

這顯然是行不通的,因爲根據這個查詢人1不低通濾波器1,如果她的教育記錄一個不帶通濾波器1。 (雖然它應該是如果她的記錄沒有通過過濾器1)。

我真的很感激任何解決方案,因爲它真的讓我難以置信。

+0

你的要求是不是100%清楚。第一個人是否應該通過過濾器1(因爲她至少有一所*所需的學校,至少有一個專業和一個畢業生)?還是應該不通過,因爲她沒有*所有*所需的學校在她的教育?請添加更多示例。 –

+0

人1通過過濾器1.正如我解釋:如果學校是一個(MIT,UT,隆德),並且主要是(經濟,民間)之一,並且是一個研究生課程,教育記錄通過過濾器1。爲了通過過濾器2,教育記錄需要哈佛作爲學校。 因此,教育記錄與教育= 1屬於人1通過過濾器1.因此,人1通過過濾器1. – user3163577

+0

對不起,但我無法檢測到您的文章中的任何信息是否人1通過過濾器1。至少有一個例子。 –

回答

2

一種方式做到這一點

SELECT f.filterid 
    FROM filters f 
    LEFT JOIN education e1 
    ON e1.uid = 1 
    AND f.filtertype = 'school' 
    AND f.value = e1.school 
    LEFT JOIN education e2 
    ON e2.uid = 1 
    AND f.filtertype = 'major' 
    AND f.value = e2.major 
    LEFT JOIN education e3 
    ON e3.uid = 1 
    AND f.filtertype = 'graduate' 
    AND f.value = e3.graduate 
GROUP BY f.filterid 
HAVING MAX(e1.educid IS NOT NULL) + 
     MAX(e2.educid IS NOT NULL) + 
     MAX(e3.educid IS NOT NULL) < 3 

SELECT f.filterid 
    FROM filters f LEFT JOIN 
(
    SELECT uid, educid, 'school' type, school value 
    FROM education 
    WHERE uid = 1 
    UNION ALL 
    SELECT uid, educid, 'major' type, major value 
    FROM education 
    WHERE uid = 1 
    UNION ALL 
    SELECT uid, educid, 'graduate' type, graduate value 
    FROM education 
    WHERE uid = 1 
) e 
    ON f.filtertype = e.type 
    AND f.value = e.value 
GROUP BY f.filterid 
HAVING MAX(f.filtertype = 'school' AND e.educid IS NOT NULL) + 
     MAX(f.filtertype = 'major' AND e.educid IS NOT NULL) + 
     MAX(f.filtertype = 'graduate' AND e.educid IS NOT NULL) < 3; 

下面是SQLFiddle演示

+0

哇,謝謝。它似乎工作。我試圖弄清楚。 – user3163577

+0

明白了。真的很棒的解決方案。 – user3163577

+0

如果這是你想要的,請考慮** [接受](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)**答案。 – peterm

1

考慮你的表如下

create table FILTERS(filterid int, filtertype varchar(100),value varchar(10)) 

insert into FILTERS values (1,'school','MIT') 

insert into FILTERS values (1,'school','UT') 

insert into FILTERS values (1,'school','Lund') 

insert into FILTERS values (1,'major','econ') 

insert into FILTERS values (1,'major','civil') 

insert into FILTERS values (1,'graduate','1') 

insert into FILTERS values (1,'school','Harvard') 

create table EDUCATION (uid int, educid int, school varchar(100),major varchar(50),graduate varchar(10)) 

insert into education values (1,1,'MIT','econ','1') 

insert into education values (1,2,'Lund','cs','0') 

請參閱下面的這些SQL - 如果它們可以有任何幫助......

select * from (
select a.uid, a.educid,a.filtertype,a.value,b.filterid, 
b.filtertype filtertype_1,b.value value_1 from (
select uid, educid,'school' filtertype,school value from education 
union all 
select uid, educid,'major' filtertype,major value from education 
union all 
select uid, educid,'graduate' filtertype,graduate value from education 
)a right outer join filters b 
on a.filtertype=b.filtertype and a.value=b.value 
) c where c.uid is null 

select * from (
select a.uid, a.educid,a.filtertype,a.value, 
b.filterid from (
select uid, educid,'school' filtertype,school value 
from education 
union all 
select uid, educid,'major' filtertype,major value 
from education 
union all 
select uid, educid,'graduate' filtertype,graduate value 
from education 
)a left outer join filters b 
on a.filtertype=b.filtertype and a.value=b.value 
) c where c.filterid is null 
1

不知道這是你在找什麼,但你會得到的想法,fiddle example here (link)

SELECT E.*, CASE WHEN (school.VALUE+major.VALUE+grad.VALUE) IS NOT NULL THEN 'PASS!' 
    ELSE 'Fail: ' + REVERSE(SUBSTRING(REVERSE(CASE WHEN school.VALUE IS NULL THEN 'school, ' ELSE '' END 
     + CASE WHEN major.VALUE IS NULL THEN 'major, ' ELSE '' END 
     + CASE WHEN grad.VALUE IS NULL THEN 'graduate, ' ELSE '' END), 3, 1000)) 
    END as Result 
FROM EDUCATION E 
LEFT JOIN FILTERS school ON school.FILTERID = 1 AND school.VALUE = E.school 
LEFT JOIN FILTERS major ON major.FILTERID = 1 AND major.VALUE = E.major 
LEFT JOIN FILTERS grad ON grad.FILTERID = 1 AND grad.VALUE = E.graduate 

或者只是得到未通過的教育,有原因爲什麼像這樣:

SELECT E.*, CASE WHEN (school.VALUE+major.VALUE+grad.VALUE) IS NOT NULL THEN 'PASS!' 
    ELSE 'Fail: ' + REVERSE(SUBSTRING(REVERSE(CASE WHEN school.VALUE IS NULL THEN 'school, ' ELSE '' END 
     + CASE WHEN major.VALUE IS NULL THEN 'major, ' ELSE '' END 
     + CASE WHEN grad.VALUE IS NULL THEN 'graduate, ' ELSE '' END), 3, 1000)) 
    END as Result 
FROM EDUCATION E 
LEFT JOIN FILTERS school ON school.FILTERID = 1 AND school.VALUE = E.school 
LEFT JOIN FILTERS major ON major.FILTERID = 1 AND major.VALUE = E.major 
LEFT JOIN FILTERS grad ON grad.FILTERID = 1 AND grad.VALUE = E.graduate 
WHERE (school.VALUE+major.VALUE+grad.VALUE IS NULL) 
+0

謝謝。這是一個好主意,但是你也可以建議一個FILTERS在FROM語法中的查詢嗎?原因是,這是一個更大的問題的一部分,其中我有非教育過濾器(如年齡,性別等)。因此我想從FILTERS表中進行選擇。 – user3163577

0
Create table #FILTERS(filterid int ,filtertype varchar(20),value varchar(20)) 
insert into #FILTERS values(1,'school','MIT') 
insert into #FILTERS values(1,'school','UT') 
insert into #FILTERS values(1,'school','Lund') 
insert into #FILTERS values(1,'major','econ') 
insert into #FILTERS values(1,'major','civil') 
insert into #FILTERS values(1,'graduate','1') 
insert into #FILTERS values(1,'school','Harvard') 


Create table #EDUCATION(uid int,educid int,school varchar(20), major varchar(20),graduate int) 
insert into #EDUCATION values(1,1,'MIT','econ',1) 
insert into #EDUCATION values(1,2,'Lund','cs',0) 
insert into #EDUCATION values(1,3,'Harvard','cs',0) 

select * from #FILTERS 
select * from #EDUCATION 

select * from #EDUCATION 
where (Exists(select 1 from #FILTERS where #FILTERS.filtertype='School' and #FILTERS.value=#EDUCATION.school) 
AND Exists(select 1 from #FILTERS where #FILTERS.filtertype='major' and #FILTERS.value=#EDUCATION.major) 
AND Exists(select 1 from #FILTERS where #FILTERS.filtertype='graduate' and #FILTERS.value=#EDUCATION.graduate) 
) 
or 
(#EDUCATION.school='Harvard') 
相關問題