【问题标题】:Advanced filter in SQLSQL 中的高级过滤器
【发布时间】:2014-12-02 16:03:22
【问题描述】:

我的 SQL 过滤有问题。请看一下数据库的架构。

现在,我想让程序员了解 PHP 并掌握技能●●/●●● 和掌握 Java 技能●●●。我执行了以下查询:

SELECT p.name, p.city FROM programmers p INNER JOIN skills s
ON p.id = s.programmer
WHERE ( s.lang = 'PHP' AND s.level > 1 ) OR ( s.lang = 'Java' AND s.level = 3 );

我得到的是

  • 约书亚,亚特兰大(因为 Java = 3)
  • 约书亚,亚特兰大(因为 PHP > 1)
  • Christopher,芝加哥(因为 PHP > 1)

但是 Christopher 不知道 Java,但他又回来了。在主要条件之间将 OR 替换为 AND 不会返回任何内容。

另外,我想一口气把程序员的所有技能都搞定;这里约书亚在两个单独的行中。如何解决?

所有事情都考虑过了,最后一个问题。获取方式:

  • 具有 PHP ●●/●●●、JS ●●● 和 HTML ●/●●/●●● 技能的程序员
  • 具有 PHP●●/●●● 和 PHP 经验 2 年以上和 JS●●● 4 年以上经验的程序员
  • 具有 PHP ●/●●/●●● 和 JS ●●● 技能的程序员,在这两种/任何一种方面至少有 3 年以上的经验

希望这是可能的。提前致谢。


编辑 以日期为中心的操作没有问题,不需要计算日期之间的差异,SQL可以只包含年份,即2010年。一般日期不是重点。

【问题讨论】:

  • @Matt ,我知道OR 是什么,我猜数据库架构可能是错误的
  • Christopher 可能不知道 Java,但他知道 Python,他会知道 OR 的意思是 OR
  • 好吧,你之前的评论肯定被删了;)
  • 我不小心把它修复了,而不是编辑哈哈 :)

标签: mysql sql database database-schema


【解决方案1】:

这是“set-within-sets”问题的一个示例。我喜欢使用聚合和having 来解决这些问题:

SELECT p.name, p.city
FROM programmers p INNER JOIN
     skills s
     ON p.id = s.programmer
GROUP BY p.name, p.city
HAVING SUM( s.lang = 'PHP' AND s.level > 1 ) > 0 AND
       SUM( s.lang = 'Java' AND s.level = 3 ) > 0;

编辑:

如果您想要技能列表(不是原始问题的一部分),请使用group_concat()

SELECT p.name, p.city, group_concat(s.lang, ':', s.level separator '; ');
FROM programmers p INNER JOIN
     skills s
     ON p.id = s.programmer
GROUP BY p.name, p.city
HAVING SUM( s.lang = 'PHP' AND s.level > 1 ) > 0 AND
       SUM( s.lang = 'Java' AND s.level = 3 ) > 0;

【讨论】:

  • 谢谢 Gordon,你的回答很好,但是当我执行请求 SELECT p.name, p.city, s.lang, s.level FROM programmers p INNER JOIN skills s (...) 我得到 name:Joshua, city:Atlanta, lang:Java and level:3,没有关于 PHP 的信息。有什么想法吗?
【解决方案2】:

这会给你你想要的,但它一点也不灵活。

select p.name, p.city, php.lang, php.level, j.lang, j.level
from   programmer p
join   skills     php
  on   php.programmer = p.id
join   skills     j
  on   j.programmer = p.id
where  php.lang = 'PHP' and php.level > 1
  and  j.lang = 'Java' and j.level = 3;

如果您要进行大量此类查询,您可能会考虑为每个技能组合创建一个视图:

create view JavaSkills as
select programmer, lang, level, exp_from
from   skills
where  lang = 'Java'

那么查询将是

select p.name, p.city, php.lang, php.level, j.lang, j.level
from   programmer p
join   PhpSkills  php
  on   php.programmer = p.id
join   JavaSkills j
  on   j.programmer = p.id
where  php.level > 1
  and  j.level = 3;

执行计划应该是相似的,但查询更容易阅读。这也很难维持,但是一个人尽其所能。 ;)

【讨论】:

    猜你喜欢
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多