【问题标题】:Oracle SQL: inline table within a SELECT statement?Oracle SQL:SELECT 语句中的内联表?
【发布时间】:2020-01-14 09:49:08
【问题描述】:

我正在配置一个将数据从系统 A 移动到系统 B 的集成工具。我提供了一个 SQL SELECT 语句,它针对系统 A 运行,该语句的输出决定了系统 B 中的更新内容。例如,要更新 Team 1 的国际销售数据:

SELECT
  'Team1_Int_Sales_Count' Code,
  count(*) Count,
  to_char(<integration tool date syntax>) Period
FROM
  Sales
JOIN
  ADozenMoreTables ON stuff
WHERE
  ADozenOpaqueFields IN ADozenOpaqueReferences
  AND Sales.Date BETWEEN <integration tool date syntax>
  AND Team = 'Team1'
  AND Sales.Type = 'International'

它使用返回的字段CodeValuePeriod 使用该值更新该期间的代码。 (字段由它们所在的顺序标识,而不是按名称。)

然后,对于Team 1的国内销售,我复制并粘贴了整个查询,并更改了代码和一个WHERE子句:

SELECT
  'Team1_Dom_Sales_Count' Code,
  <otherwise as above>
  AND Sales.Type = 'Domestic'

然后我为第 2 组和第 3 组再复制粘贴四次

SELECT
  'Team2_Int_Sales_Count' Code,
  <snip>
  AND Team = 'Team2'
  AND Sales.Type = 'International'

SELECT
  'Team2_Dom_Sales_Count' Code,
  <snip>
  AND Team = 'Team2'
  AND Sales.Type = 'Domestic'

SELECT
  'Team3_Int_Sales_Count' Code,
  <snip>
  AND Team = 'Team3'
  AND Sales.Type = 'International'

SELECT
  'Team3_Dom_Sales_Count' Code,
  <snip>
  AND Team = 'Team3'
  AND Sales.Type = 'Domestic'

完整的问题有一个 ~60 行的 SELECT 语句,具有 3x3x3 排列,所涉及的复制/粘贴量让我感到恐惧。

有没有什么方法可以编写一条 SQL SELECT 语句,该语句将逐步遍历所有排列而无需复制粘贴重复?在我看来,我会在一个临时表中内联创建排列,或者作为一个二维数组,查询可以返回代码和其他两个字段匹配的值:

      { {'Team1_Int_Sales_Count', 'Team1', 'International'},
        {'Team1_Dom_Sales_Count', 'Team1', 'Domestic'},
        {'Team2_Int_Sales_Count', 'Team2', 'International'},
        {'Team2_Dom_Sales_Count', 'Team2', 'Domestic'},
        {'Team3_Int_Sales_Count', 'Team3', 'International'},
        {'Team3_Dom_Sales_Count', 'Team3', 'Domestic'} } Permutations

这里的约束是集成工具要求我为每个任务提供一个 SELECT 语句。我不能在它前面加上WITH 语句,或者声明函数,或者将复杂的查询作为视图存储在源数据库中,或者做任何有趣或好的事情。它是一个 Oracle ODBC 连接,所以它使用 Oracle SQL。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    你似乎想要一个交叉连接。

    SELECT t.team || ct.code code,
           t.team,
           ct.type
           FROM (SELECT '_Int_Sales_Count' code,
                        'International' type
                        FROM dual
                 UNION ALL
                 SELECT '_Dom_Sales_Count' code,
                        'Domestic' type
                        FROM dual) ct
                CROSS JOIN (SELECT 'Team1' team
                                   FROM dual
                            UNION ALL
                            SELECT 'Team2' team
                                   FROM dual
                            UNION ALL
                            SELECT 'Team3' team
                                   FROM dual) t;
    

    db<>fiddle

    【讨论】:

      【解决方案2】:

      排列表可以这样构造:

      SELECT
        Permutations.Code AS Code,
        COUNT(*) AS Count,
      ...
      JOIN (SELECT * FROM (
              (SELECT 'Team1_Int_Sales_Count' AS Code, 'Team1' AS Team, 'International' AS Type FROM Dual),
        UNION (SELECT 'Team1_Dom_Sales_Count' AS Code, 'Team1' AS Team, 'Domestic'      AS Type FROM Dual),
        UNION (SELECT 'Team2_Int_Sales_Count' AS Code, 'Team2' AS Team, 'International' AS Type FROM Dual),
        UNION (SELECT 'Team2_Dom_Sales_Count' AS Code, 'Team2' AS Team, 'Domestic'      AS Type FROM Dual),
        UNION (SELECT 'Team3_Int_Sales_Count' AS Code, 'Team3' AS Team, 'International' AS Type FROM Dual),
        UNION (SELECT 'Team3_Dom_Sales_Count' AS Code, 'Team3' AS Team, 'Domestic'      AS Type FROM Dual)
      )) AS Permutations
      ON Permutations.Team = Sales.Team AND Permutations.Type = Sales.Type
      WHERE...
      

      【讨论】:

        【解决方案3】:

        我会这样做:

        with 
          team as (select  level lv from dual connect by level <= 3)
        , bas  as (select '_Int_Sales_Count' n_count, 'International' type from dual
               union all select '_Dom_Sales_Count' n_count, 'Domestic' type from dual)
        , permutations as 
             ( select 'Team' || lv ||n_count   as code,  'Team' || lv as team, type from team join bas on (1=1))
        select * from permutations
        

        但有限制:

        select 'Team' || lv ||n_count   as code,  'Team' || lv as team, type from
              (select  level lv from dual connect by level <= 3) team,
              (select '_Int_Sales_Count' n_count, 'International' type from dual
                   union all select '_Dom_Sales_Count' n_count, 'Domestic' type from dual) bas  
        

        【讨论】:

        • 谢谢,但是这个集成工具的限制是第一个关键字必须是SELECT。也许我应该在问题中更清楚地说明这一点。
        猜你喜欢
        • 2011-12-01
        • 1970-01-01
        • 2011-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-28
        相关资源
        最近更新 更多