SQL百分比优雅

时间:2017-10-14 12:40:37

标签: sql postgresql syntax

我刚刚开始熟悉SQL,我发现语言很容易,但有时也很混乱。例如,采用这个陈述

SELECT t.ID, dt, b.package_name as "Package Name",
       SUM(amount_usd) as amount_usd, SUM(unit_sales) as unit_sales, 
       SUM(amount_usd) * 1.0 / SUM(amount_usd) OVER () as ratio
FROM transaction t JOIN
     bundles b
     ON t.package_id = cast(b.id as INT)
WHERE (t.code = 'AA') AND
      (t.country_code = 'US') AND
      (dt BETWEEN '2016-01-01' and '2016-01-04')
GROUP BY t.ID, dt, "Package Name"
ORDER BY t.ID
LIMIT 1000;

我发现有一点浪费,必须重复SELECT plus FROM才能正确计算百分比。是否有更优雅的解决方案来避免这类事情?

以下是我修复它的方法。

如果你想要总和的百分比,你不需要筑巢

SELECT t.ID, dt, b.package_name as "Package Name",
       SUM(amount_usd) as amount_usd, SUM(unit_sales) as unit_sales, 
       SUM(amount_usd) * 1.0 / SUM(amount_usd) OVER (PARTITION BY dt) as ratio
FROM transaction t JOIN
     bundles b
     ON t.package_id = cast(b.id as INT)
WHERE (t.code = 'AA') AND
      (t.country_code = 'US') AND
      (dt BETWEEN '2016-01-01' and '2016-01-04')
GROUP BY t.ID, dt, "Package Name"
ORDER BY t.ID
LIMIT 1000;

如果您想要收入与每天总收入之比

{{1}}

1 个答案:

答案 0 :(得分:0)

SQL的大多数方言都支持ANSI标准窗口函数。此外,格式化通常在以后的应用程序中处理。

所以,这通常写成:

SELECT t.ID, dt, b.package_name as "Package Name",
       SUM(amount_usd) as amount_usd, SUM(unit_sales) as unit_sales, 
       SUM(amount_usd) * 1.0 / NULLIF(SUM(SUM(amount_usd)) OVER ()) as ratio
FROM transaction t JOIN
     bundles b
     ON t.package_id = cast(b.id as INT)
WHERE (t.code = 'AA') AND
      (t.country_code = 'US') AND
      (dt BETWEEN '2016-01-01' and '2016-01-04')
GROUP BY t.ID, dt, "Package Name"
ORDER BY t.ID
LIMIT 1000;

您的查询中的其他问题:

  • 当查询包含多个表时,限定所有列名称。
  • 使用表缩写作为表别名 - 更容易编写和阅读。
  • 不同表上的JOIN键应该是相同的类型。事实上,它们应该被宣布为适当的外键关系。
  • 您在SELECT中遗漏了一些汇总函数。确保唯一的未聚合列是GROUP BY键。

如果您的数据库供应商不支持ANSI标准功能,那么您应该使用它们。