Complex select in loop(基于之前的解决方案)

Complex select in loop (based on a previous solution)

我在这里问了一个问题:

我得到了一个完美的答案,但现在我需要在复杂的 select 语句中使用它。

目标是在连接到查询的列中获得相同的结果。例如:

  SELECT t1.phone_number
       , t2.origin_country
       , sum(t1.volume) Total_vol
       , sum(t1.charge) Total_chg
       from t2
     LEFT JOIN t1 ON t1.item_no = t2.item_no
     LEFT JOIN t3 ON t3.vcode = t2.vcode
     LEFT JOIN /*<<Here should be a subquery which attach the column with
     the countries to my query>>*/
       +many WHERE and GROUP BY clauses

问题是列数和源 table 可能会有所不同,因此我正在寻找一种灵活的解决方案,我可以将其用于任何存在 phone_number 列的复杂查询。我已经尝试过的:

那么我应该怎么做呢?

(如果有人有完全不同的方法来灵活地在 table 中识别和显示 phone 数字,欢迎他们)

--更新--

解决方法:

  select ... PHONE_NUMBER, XY, ZZ, ... ,
         case
         when i.INT_CODE = substr(PHONE_NUMBER,1,4) then i.COUNTRY

         when i.INT_CODE = substr(PHONE_NUMBER,1,3) 
         and i.INT_CODE = substr(PHONE_NUMBER,1,4) then i.COUNTRY

         when i.INT_CODE = substr(PHONE_NUMBER,1,2) 
         and i.INT_CODE = substr(PHONE_NUMBER,1,3) then i.COUNTRY

         when i.INT_CODE = substr(PHONE_NUMBER,1,1) 
         and i.INT_CODE = substr(PHONE_NUMBER,1,2) then i.COUNTRY

         else 'Unidentified location'
         end TARGET_COUNTRY

   from  (
          select ... t1.phone_number ,sum(xy) Total XY, sum(zz) ZZ, ... 
             /*same fields like in the main query above*/
          left join t2 on ...
          left join t3 on ...

          where date = 'some date' and country in ('country1','country2') ...
             /*many conditions*/
          group by t2.phone_number,
                   t3.account ... 
          ) MainQuery

  left join int_codes i
  on (    i.INT_CODE = substr(MainQuery.PHONE_NUMBER, 1, 1)
       or i.INT_CODE = substr(MainQuery.PHONE_NUMBER, 1, 2)
       or i.INT_CODE = substr(MainQuery.PHONE_NUMBER, 1, 3)
       or i.INT_CODE = substr(MainQuery.PHONE_NUMBER, 1, 4)
     );

如果您使用的是 Oracle 12c,那么您可以使用 LATERAL VIEW
使用确定正确国家代码的子查询:

SELECT .........
FROM T_NUMBERS t
LEFT JOIN ..............
LEFT JOIN ................
, /* this comma is required by the syntax */
LATERAL (
  SELECT * FROM int_codes i
  WHERE i.INT_CODE = substr(t.PHONE_NUMBER, 1, 1 )
     OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 2 )
     OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 3 )
     OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 4 )
  ORDER BY length( i.INT_CODE ) DESC
  FETCH FIRST 1 ROWS ONLY
)
GROUP BY .....;

此外,假设T_NUMBERS有一些唯一标识每一行的主键列,那么你可以使用这个子查询和MERGE语句一起更新T_NUMBERS table
使用正确的国家代码和名称,以这种方式(假设 PK 是主键列):

MERGE INTO T_NUMBERS  t
USING (
  SELECT t.pk, i.country, i.int_code
  FROM T_NUMBERS t,
  LATERAL (
    SELECT * FROM int_codes i
    WHERE i.INT_CODE = substr(t.PHONE_NUMBER, 1, 1 )
       OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 2 )
       OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 3 )
       OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 4 )
    ORDER BY length( i.INT_CODE ) DESC
    FETCH FIRST 1 ROWS ONLY ) i
) i
ON ( t.pk = i.pk )
WHEN MATCHED THEN UPDATE SET t.COUNTRY = i.COUNTRY, t.COUNTRY_CODE = i.int_CODE;
;

----- 编辑 -----

在 Oracle 11g 上,您可以尝试类似下面的操作
- 但仍然假设 T_NUMBERS table 有一些主键列(在下面的查询中,此列名为 pk):

SELECT ........
 FROM (
      SELECT t.pk, t.phone_number,
             i.int_code, i.country,
             aaa.*, bbb.*
             row_number() over( partition by pk order by length(i.int_code) desc ) xxxx
      FROM T_NUMBERS t
      LEFT JOIN aaa   ......
      LEFT JOIN bbb   ......
      LEFT JOIN int_codes i
      ON (    i.INT_CODE = substr(t.PHONE_NUMBER, 1, 1 )
           OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 2 )
           OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 3 )
           OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 4 )
        ) 
)
WHERE xxxx = 1
GROUP BY ........ ;

我不确定它会如何执行,可能会很慢。

下面的版本可能会稍微好一点:

SELECT ........
 FROM (
      SELECT t.pk, t.phone_number,
             i.int_code, i.country,
             row_number() over( partition by pk order by length(i.int_code) desc ) xxxx
      FROM T_NUMBERS t

      LEFT JOIN int_codes i
      ON (    i.INT_CODE = substr(t.PHONE_NUMBER, 1, 1 )
           OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 2 )
           OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 3 )
           OR i.INT_CODE = substr(t.PHONE_NUMBER, 1, 4 )
        ) 
)
LEFT JOIN aaa   ......
LEFT JOIN bbb   ......
WHERE xxxx = 1
GROUP BY ........ ;