使用按功能分组时Teradata的计算列语法

时间:2018-09-25 05:08:38

标签: sql teradata

我正在尝试添加以OTYPE的百分比计算的列。 IE浏览器 订单类型|现状每种状态下的订单量|此状态下所有订单的百分比

SELECT 
T.OTYPE,
STATUS_CD,
COUNT(STATUS_CD) AS STATVOL,
(STATVOL / COUNT(ROW_ID)) * 100

FROM Database.S_ORDER O

LEFT JOIN /* Finding definitions for status codes & attaching */
(
SELECT 
ROW_ID AS TYPEJOIN,
"NAME" AS OTYPE
FROM database.S_ORDER_TYPE
) T

ON T.TYPEJOIN = ORDER_TYPE_ID


GROUP BY (T.OTYPE, STATUS_CD)
/*Excludes pending and pending online orders */
WHERE  CAST(CREATED AS DATE) =  '2018/09/21'  AND  STATUS_CD <> 'Pending' 
AND STATUS_CD <> 'Pending-Online'
ORDER BY T.OTYPE, STATUS_CD DESC

OTYPE   STATUS_CD                    STATVOL TOTALPERC
Add New Service Provisioning         2,740   100
Add New Service In-transit           13      100
Add New Service Error - Provisioning 568     100
Add New Service Error - Integration  1       100
Add New Service Complete             14,387  100

当前输出仅在每行输出100,需要占订单总数的百分比

有人可以帮助Teradata&SQL学生吗? 使这个问题变得困难的复杂因素是我对group by的理解,count语法是微不足道的。我花了些时间才显示它,我不确定如何在此组合中引入计算列。

预先感谢

3 个答案:

答案 0 :(得分:0)

总共可以完成几个地方,但这就是我要做的方式。我还清理了您不需要的其他子查询,并将日期更改为无歧义的格式(如果遇到Teradata中的问题,请改回日期)

SELECT 
    T."NAME" as OTYPE,
    STATUS_CD,
    COUNT(STATUS_CD) AS STATVOL,
    COUNT(STATUS_CD)*100/TotalVol as Pct
FROM database.S_ORDER O
LEFT JOIN EDWPRDR_VW40_SBLCPY.S_ORDER_TYPE T on T.ROW_ID = ORDER_TYPE_ID
cross join (select count(*) as TotalVol from database.S_ORDER) Tot
GROUP BY T."NAME", STATUS_CD, TotalVol
WHERE  CAST(CREATED AS DATE) =  '2018-09-21'  AND  STATUS_CD <> 'Pending' AND STATUS_CD <> 'Pending-Online'
ORDER BY T."NAME", STATUS_CD DESC

答案 1 :(得分:0)

  1. where clausegroup by子句之前,因此查询 问题中显示的内容无效。
  2. 始终每个列引用加上相关的表别名,在下面,我假设您没有在其中使用属于订单表的别名。
  3. 对于此左联接,您可能不需要子查询。虽然有时需要子查询或提高性能的子查询在这里似乎不是这种情况。
  4. 大多数现代的SQL兼容数据库都提供“窗口函数”,而Teradata做到了。它们非常有用,在这里,当您将count()over clause结合使用时,可以得到所有行的总数,而无需其他子查询或联接。
  5. 因为问题既没有提供样本数据,也没有提供预期结果,我实际上并不知道计算百分比真正需要的数字。相反,我选择向您展示不同的计数方式,以便您选择正确的方法。我怀疑您的每一行都会得到100,因为count(status_cd)等于count(row_id)。您需要对status_cd进行计数,而不是对row_id进行计数。 nb:对于每个非空值
  6. count()函数将增加1
  7. 我更改了日期过滤器的应用方式。更改每一行上的数据以适合where子句中的常量的效率不高。保持数据不变,并更改应用过滤器以适合数据的方式,这几乎总是更有效(搜索sargable

SELECT
    t.OTYPE
  , o.STATUS_CD
  , COUNT(o.STATUS_CD)          count_status
  , COUNT(t.ROW_ID              count_row_id
  , count(t.row_id) over()      count_row_id_over
FROM dbo.S_ORDER o
    LEFT JOIN dbo.S_ORDER_TYPE t ON t.TYPEJOIN = o.ORDER_TYPE_ID
    /*Excludes pending and pending online orders */
WHERE o.CREATED >= '2018-09-21' AND o.CREATED <  '2018-09-22'
    AND o.STATUS_CD <> 'Pending'
    AND o.STATUS_CD <> 'Pending-Online'
GROUP BY
    t.OTYPE
  , o.STATUS_CD
ORDER BY
    t.OTYPE
  , o.STATUS_CD DESC

答案 2 :(得分:0)

正如@TomC已经指出的,不需要联接到派生表。获取百分比的最简单方法是基于 Group Sum 。我还将日期更改为标准SQL 日期文字,并将where移到了group by之前。

SELECT 
   t."NAME",
   o.STATUS_CD,
   Count(o.STATUS_CD) AS STATVOL,
-- rule of thumb: multiply first then divide, otherwise you will get unexpected results
-- (Teradata rounds after each calculation)
   100.00 * STATVOL / Sum(STATVOL) Over ()

FROM database.S_ORDER AS O
 /* Finding definitions for status codes & attaching */
LEFT JOIN database.S_ORDER_TYPE AS t
  ON t.ROW_ID = o.ORDER_TYPE_ID

/*Excludes pending and pending online orders */
 -- if o.CREATED is a Timestamp there's no need to apply the CAST
WHERE Cast(o.CREATED AS DATE) =  DATE '2018-09-21'
  AND o.STATUS_CD NOT IN ('Pending', 'Pending-Online')

GROUP BY (T.OTYPE, o.STATUS_CD)

ORDER BY T.OTYPE, o.STATUS_CD DESC

顺便说一句,您可能不需要外部连接内部应该返回相同的结果。