如何在SQL中将标量子查询转换为条件OLAP函数?

时间:2019-03-09 16:47:13

标签: sql nested teradata olap

我正在使用Teradata 15.10。我有一个包含两列last_name和first_name的表。对于每一行,我需要计算出有多少行具有相同的last_name和first_name,但其值相反,并显示该计数(即使它等于0)。目前,我正在使用以下查询:

SELECT LAST_NAME, 
       FIRST_NAME,
      (SELECT Count(*)
       FROM   myTable AS T1
       WHERE  T1.FIRST_NAME = T2.LAST_NAME
         AND  T1.LAST_NAME  = T2.FIRST_NAME) AS REVERSE_NAME_COUNT
FROM myTable AS T2

不幸的是,这不是很快,我还有很多其他列在进行这种计数。我想知道是否有一种方法可以将上面的标量子查询转换成这样的OLAP函数:

SUM(CASE WHEN T1.FIRST_NAME = T2.LAST_NAME AND T1.LAST_NAME = T2.FIRST_NAME THEN 1 ELSE 0 END) OVER(ROWS UNBOUNDED PRECEDING)

但是据我了解,无法访问分区中当前正在处理的值。还有什么其他方法可以编写子查询?

输入示例:

       FIRST_NAME        LAST_NAME
----------------------------------
           SYLVIE           BOUVET
         LUCIENNE             BRUN
           BOUVET           SYLVIE
         FRANCINE            CARON
             BRUN         LUCIENNE
             BRUN         LUCIENNE
            KEVIN         MACHETEL
             REMI        MINVIELLE
          QUENTIN        THUILLIER
        MINVIELLE             REMI

所需的输出示例:

       FIRST_NAME        LAST_NAME  REVERSE_NAME_COUNT
------------------------------------------------------
           SYLVIE           BOUVET                   1
         LUCIENNE             BRUN                   2
           BOUVET           SYLVIE                   1
         FRANCINE            CARON                   0
             BRUN         LUCIENNE                   1
             BRUN         LUCIENNE                   1
            KEVIN         MACHETEL                   0
             REMI        MINVIELLE                   1
          QUENTIN        THUILLIER                   0
        MINVIELLE             REMI                   1 

2 个答案:

答案 0 :(得分:2)

您是否在谈论Select中的标量子查询

SELECT
   last_name
  ,(
     SELECT Count(*)
     FROM   myTable AS T1
     WHERE  T1.FIRST_NAME = T2.LAST_NAME
   )
FROM myTable AS t2

那您是对的,您不能将其重写为OLAP函数。

那些标量子查询的性能确实很差,但是您通常可以使用外部联接重写它们:

SELECT
   t2.last_name
  ,t1.Cnt 
FROM myTable AS t2 
LEFT JOIN
 ( 
   SELECT first_name, Count(*) AS Cnt
   FROM myTable
   GROUP BY 1
 ) AS t1
ON T1.FIRST_NAME = T2.LAST_NAME

答案 1 :(得分:0)

感谢@dnoeth,我找到了解决方法。

SELECT
   T2.first_name
   T2.last_name
  ,SUM(t1.Cnt) 
FROM myTable AS T2 
LEFT JOIN
 ( 
   SELECT first_name, last_name, Count(*) AS Cnt
   FROM myTable
   GROUP BY 1, 2
 ) AS T1
ON T1.first_name = T2.last_name
AND T1.last_name = T2.first_name
GROUP BY 1, 2