如何只匹配匹配条件的第一行?

时间:2014-06-06 19:18:04

标签: sql oracle

这是我的数据:

  INT       CHAR(2)         CHAR(4)
+------+--------------+------------+
|  ID  |  SHORT_CODE  | LONG_CODE  |
+------+--------------+------------+
|   1         01           0100
|   2         01           0110
|   3         01           0120
|   4         02           0200
|   5         02           0212
|   6         02           0299
|   7         02           0211

我正在寻找将输出此结果的查询:

+--------------+------------+-------------+
|  SHORT_CODE  | LONG_CODE  |   IS_FIRST  |
+--------------+------------+-------------+
|     02           0200          false
|     02           0211          true
|     02           0212          false
|     02           0299          false

这是我试过的

SELECT 
    short_code,
    long_code,
    CASE
       WHEN long_code LIKE '021%'
       THEN 'true'
       ELSE 'false'
    END as is_first
FROM
    MY_TABLE
WHERE
    short_code='02'
ORDER BY
    long_code ASC;

此查询还会为true打印0212。我希望true仅用于第一个匹配的行。

我怎样才能实现这一目标?

此问题中的示例代码可用here

Oracle 10gR2

3 个答案:

答案 0 :(得分:1)

您可以创建一个额外的列is_match,以显示该行是否与like '021%'条件匹配。然后,您可以在匹配的行分区和不匹配的行分区中分配升序行号rn。匹配且行号为1的行是您要查找的行。

SELECT  short_code
,       long_code
,       CASE
        WHEN is_match = 1 and rn = 1 THEN 'true'
        ELSE 'false'
        END as is_first
FROM    (
        SELECT  short_code
        ,       long_code
        ,       is_match
        ,       row_number() over (
                    partition by is_match
                    order by long_code) as rn
        FROM    (
                SELECT  short_code
                ,       long_code
                ,       case 
                        when long_code like '%021%' then 1
                        else 0
                        end as is_match
                FROM    MY_TABLE
                WHERE   short_code = '02'
                ) s1
        ) s2
ORDER BY
        long_code;

See it working at SQL Fiddle.

答案 1 :(得分:1)

你可以用jimmy-rig row_number()来做这件事,但这可能有点麻烦。 我能找到的最好的想法是创建一个伪列prefix,这样我就可以先排序所有匹配的行,然后按long_code排序:

SELECT  short_code, 
        long_code, 
        CASE row_number() over (order by prefix desc, long_code asc) 
           WHEN 1 THEN 'true' 
           ELSE 'false' 
        END AS is_first
FROM    (SELECT short_code,
                long_code,
                CASE
                   WHEN long_code LIKE '021%' THEN 1
                   ELSE 0
                END as prefix
          FROM  my_table
          WHERE short_code='02'
         )
ORDER BY long_code ASC;

结果也显示在SQLFiddle

答案 2 :(得分:0)

SELECT m.*,
(CASE WHEN b.Id IS NOT NULL THEN 'True' ELSE 'False' END) as First
FROM MY_TABLE m
LEFT JOIN 
(
    SELECT Id FROM
    (
    SELECT Id 
    FROM MY_TABLE
    WHERE Long_Code LIKE '021%'
    AND Short_Code = '02'
    ORDER BY Long_Code
    ) C
    WHERE RowNum = 1
 ) B
 ON b.Id = m.Id
 WHERE m.Short_Code = '02';