编写查询以包含某些值,但在查找最新时间段时排除其他值

时间:2014-03-28 14:46:52

标签: sql syntax

我正在尝试编写一个查询,查找具有最新期间(年)的特定代码的人,但是如果他们有另一个具有该最新期间(年)的代码则不会。我会明确的,所以我的榜样是有道理的。

我希望拥有代码A1,A2,A3,A4,A5而不是AG,AP,AQ的人。有些人拥有一段时间的A1代码(如2014年)和同一时期的AG代码。我想排除它们。并非每个人都有代码,因此字段值可能为NULL

有没有办法以不同的方式表达这一点(即字符数量少)?

SELECT 
    people.firstName
FROM 
    people
WHERE EXISTS (
    SELECT *
    FROM codes
    WHERE 
        codes.people_id = people.id
        AND period = (SELECT MAX(period) FROM codes codes2 WHERE codes2.people_id = codes.people_id)
        AND code LIKE 'A[1-5]'
)
AND NOT EXISTS (
    SELECT *
    FROM codes
    WHERE 
        codes.people_id = people.id
        AND period = (
            SELECT MAX(period) 
            FROM codes codes2 
            WHERE codes2.people_id = codes.people_id
        )
         AND code LIKE 'A[GPQ]'
)

架构如下:

  • id(PK)
  • 的firstName

代码

  • people_id(FK)与People表的多对一关系
  • 代码(例如“A1”,“A2”,“AG”)
  • 期间(例如“2013”​​,“2014”)

1 个答案:

答案 0 :(得分:0)

你有很多方法可以做到这一点,我不是SQL专家,但我不能看到你的查询太糟糕了,如果你想尝试减少你可以考虑使用的子查询的数量GROUP BY clause以及SUM中的Aggregate function HAVING clause

我开始按如下方式更新您的代码:

SELECT 
    people.firstName
FROM 
    people
    LEFT JOIN codes AS a15 ON a15.people_id = people.id AND a15.code LIKE 'A[1-5]'
    LEFT JOIN codes AS agpq ON agpq.people_id = people.id AND agpq.code LIKE 'A[GPQ]'
GROUP BY
    people.firstName
HAVING
    SUM(CASE WHEN a15.code IS NULL THEN 0 ELSE 1 END) > 0
    AND SUM(CASE WHEN agpq.code IS NULL THEN 0 ELSE 1 END) = 0

然而,这并未考虑与描述的期间特定要求有关的任何事项。您可以将句点添加到GROUP BY子句或将其添加到WHERE或其中一个JOIN约束中,但我不完全确定您的描述中确切的内容(我不相信这是通过你自己的任何错误,我只是不能亲自对齐提供给描述的代码)。

我还想指出,上面的SUM函数无法准确计算匹配代码的数量。这是因为如果A[GPQ]A[1_5]都返回至少一行,则每个约束返回的数字将乘以另一个约束返回的数字,但它可用于确定是否存在“任何“退回的项目,如果条件匹配,它将具有SUM(...) > 0

我确信一个更有经验的SQL Developer / DBA将能够在我提出的查询中挖出许多漏洞,但它可能会给他们或其他人一些工作,并希望能为您提供使用子查询的替代方案的想法。