嵌套查询将获取分组结果

时间:2018-02-23 20:26:35

标签: mysql sql mariadb greatest-n-per-group

我有以下查询:

 SELECT * from `provider_info` where provnum not in 
 (select pi_provnum from prov_index where length(pi_provnum)=6)
 and length(provnum)=6 group by provnum

prov_index每个provnum / pi_provnum只有一行。但是provider_info每个provnum可以有多行。

我基本上从第二个表中的提供者(provnum / pi_provnum)没有条目的一个表中提取行。内部查询给出了一个provnum列的列表,这些列存在于provider_info表中但在prov_index表中不存在。 (length()条件是查询中需要的额外内容)

由于在provider_info中可能有多个具有相同provnum的条目,因此我使用了" group"' group by provnum'条款只给我一个例子。但我最终需要所有与最新' sourcedate'值。

  1. 有没有办法使用DISTINCT而不是GROUP子句?

  2. 最终,我需要从provider_info返回一个特定的行(所有列),即列中最新日期的行" soucedate"

  3. 我已尝试过此功能但不起作用:

     SELECT * from `provider_info` where provnum not in 
     (select pi_provnum from prov_index where length(pi_provnum)=6) 
     and length(provnum)=6 order by provnum,sourcedate desc group by provnum 
     having sourcedate=max(sourcedate)
    

    基本上我想要的是来自provider_info的一行列表,其中包含最新的sourcedate列,其中provnum不存在于第二个表prov_index中。关键是我想要最后一行中的所有列,而不仅仅是max(sourcedate)

    这可以在一个复杂的查询中完成吗?

2 个答案:

答案 0 :(得分:0)

您可以使用NOT EXISTS子句。如果您在provider_info中有相同的provnum和相同的sourcedate(最新日期),则它有一个可以返回重复行的情况。如果在您的方案中不可能,或者在这种情况下您想要两个行,则可以这样做:

SELECT p1.* 
from `provider_info` p1 where p1.provnum not in 
(select pi_provnum from prov_index where length(pi_provnum)=6) 
and length(p1.provnum)=6
AND NOT EXISTS (
    SELECT * FROM provider_info p2 where p1.provnum = p2.provnum AND p1.sourcedate > p2.sourcedate 
)

Sidenote,我还会将“*”替换为您希望查询返回的实际字段列表。

答案 1 :(得分:0)

我会像这样进行查询:

 SELECT p.*
   FROM
        ( -- latest sourcedate for each provnum
          SELECT s.provnum
               , MAX(s.sourcedate) AS latest_sourcedate
            FROM `provider_info` s
           WHERE LENGTH(s.provnum) = 6
           GROUP
              BY s.provnum
        ) q

     -- row(s) that matches latest sourcedate
   JOIN `provider_info` p
     ON LENGTH(p.provnum) = 6
    AND p.provnum         = q.provnum
    AND p.sourcedate      = q.latest_sourcedate

     -- anti-join exclude rows that have a match
   LEFT
   JOIN prov_index i
     ON LENGTH(i.pi_provnum) = 6
    AMD i.pi_provnum = p.provnum
  WHERE i.pi_provnum IS NULL

  ORDER BY ...

让我们解开一下。

内联视图(派生表格) q provnum获取provider_info的不同值,并为每个sourcedate添加provider_info。< / p>

我们可以将该结果加入provnum,并获取与sourcedate匹配的行,并使latest_sourcedateprov_index匹配。

要排除行,我更喜欢使用反连接模式而不是NOT IN。这样做的方式,我们做一个外部连接来查找WHERE的匹配行。 LEFT外连接将返回左侧的所有行,以及右侧的匹配。诀窍是在pi_provnum子句中使用排除找到匹配的行的条件。连接谓词保证匹配的行将具有pi_provnum的非NULL值。因此,如果我们排除具有非NULL值的行,即仅返回{{1}}的NULL值的行,那么我们剩下的是来自左侧的行没有匹配。