枚举where或join语句中的列值

时间:2014-07-25 21:23:49

标签: sql oracle

这是在Oracle SQL中。我无法更改表格,只查询已有的表格。

我有一个包含不同类型地址的地址表。主要,邮寄,位置,EOB。我有一张发给不同人的支票表。

Addresses
Group_ID             Type    
01                   Primary
02                   Location
02                   Primary
03                   Mailing
03                   EOB

Checks
AMT                  Group_ID
350.05               01
410.62               02
  1.05               03

我有一个优先级列表,将地址类型排序为:Primary,Mailing,EOB,Location。我试图找出如何编写JOIN或WHERE语句,以便我只返回为该组ID列出的最高地址类型的支票。

示例:

AMT        Group_ID    Type
350.05     01          Primary
410.62     02          Primary
  1.05     03          Mailing

等。基本上枚举位置类型并获取MIN值。不幸的是,我无法添加排名列或类似的内容。

3 个答案:

答案 0 :(得分:1)

您可以使用ROW_NUMBER()函数和CASE语句执行此操作:

;
WITH cte AS (SELECT "AMT"
                   ,a."Group_ID"
                   ,b."Type"
                   ,ROW_NUMBER() OVER(PARTITION BY a."Group_ID" 
                                      ORDER BY CASE WHEN b."Type" = 'Primary' THEN 1
                                                       WHEN b."Type" = 'Mailing' THEN 2
                                                       WHEN b."Type" = 'Location' THEN 3
                                                       WHEN b."Type" = 'EOB' THEN 4
                                                       ELSE 5
                                                  END) AS RN

              FROM Checks a
              JOIN Addresses b
               ON a."Group_ID" = b."Group_ID"
               )
SELECT "AMT","Group_ID","Type"
FROM cte
WHERE "RN" = 1

演示:SQL Fiddle

你也可以用同样的方式使用排名功能。

答案 1 :(得分:1)

另一种可能性如下;通过在内部查询中获取MAX() Type并加入它。

select c.AMT,
tab."Group_ID",
tab.max_type
from checks c
join
(
select "Group_ID",
max("Type") as max_type
from Addresses
group by "Group_ID"
) tab on c."Group_ID" = tab."Group_ID"

这将导致:

AMT     GROUP_ID    MAX_TYPE
350      1           Primary
411      2           Primary
1        3           Mailing

查看DEMO Here

答案 2 :(得分:1)

这是@ GoatCO解决方案的一个小变种。我更喜欢它,因为它在 join之前而不是之后执行分析函数

SELECT c.amt, c.Group_ID, a.Type
FROM checks c left join
     (select a.*,
             row_number() over (partition by a.Group_ID
                                order by (case when a."Type" = 'Primary' then 1
                                               when a."Type" = 'Mailing' then 2
                                               when a."Type" = 'Location' then 3
                                               when a."Type" = 'EOB' then 4
                                               else 5
                                         )
                                ) as seqnum
      from addresses a
     ) a
     on c.Group_ID = a.Group_id and a.seqnum = 1;