令人难以置信的SQL难题

时间:2014-01-30 09:19:42

标签: mysql sql sql-server

对不起标题。我现在不能带来任何有意义的东西但是如果你建议我会更新它。

好吧,这个问题已经困扰了我好几天了,让我发疯了。

我有一个数据库,可以保存与教育相关的过滤器。

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.如果学校是(MIT,UT或Lund)之一,教育记录通过filter1,而主要是(经济或民用)之一,并且是研究生课程。 为了通过过滤器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,civil}并且是研究生计划。但是,教育记录1没有通过过滤器2,因为学校是麻省理工学院,而不是哈佛大学。

教育记录2没有通过过滤器1,因为主要(cs)不在{econ,civil},并且它没有通过过滤器2,因为学校是Lund,而不是哈佛。

如果她的教育记录都没有通过过滤器1,则人员1不会传递过滤器1。 因此,人1通过过滤器1(因为她的第一个教育记录通过了过滤器1),但没有通过过滤器2,因为没有一个教育记录通过过滤器2。

我的目标是选择人1未通过的过滤器的过滤器。

这是我到目前为止所得到的:

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,则应该是这样。)

我真的非常感谢任何解决方案,因为它真的令人难以置信。

4 个答案:

答案 0 :(得分: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 演示

答案 1 :(得分: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

答案 2 :(得分: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)

答案 3 :(得分: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')