【问题标题】:Multiplying Subqueries in Postgres在 Postgres 中乘以子查询
【发布时间】:2014-03-16 07:34:59
【问题描述】:

自从我开始学习 pgsql 以来已经有一段时间了,我正在尝试处理我的第一个项目(只是为了测试自己)并且我一直在努力完成这项工作。

SELECT ((SELECT to_number(g.grade, '9D99') AS numgrade
           FROM grade g, registration r
           WHERE g.grade_id=r.grade_id 
            AND g.grade!='INC'
            AND g.grade!='INP'
            AND g.grade!='W'
            AND g.grade!='DRP')*(SELECT s.subjunits
                         FROM subject s, registration r
                         WHERE s.subjcode=r.subjcode)) AS product
FROM subject s, registration r;

所以,我想要做的是乘以 grade 列(以防万一你没有注意到, grade 列是 character 这就是我放 @987654326 的原因@) 来自表 registration 和列 subjunits 来自表 subject

我有点发现 Postgres 不允许多行相乘,或者它可能不允许返回多行。无论哪种方式,我仍然想知道是否有另一种方法可以获取我选择的行的乘积?

将每个主题都放在WHERE 子句中非常不方便。

【问题讨论】:

  • 在以后的问题中,请始终显示任何错误消息的确切文本,以及您的 PostgreSQL 版本 (select version()),以及可能的示例数据和表定义。您可能还想查看sqlfiddle.com
  • @CraigRinger 哦,我明白了。我会。谢谢! :)

标签: sql postgresql subquery multiplication


【解决方案1】:
SELECT (to_number(g.grade, '9D99') * s.subjunits) AS product
  FROM grade g, registration r, subject s
  WHERE g.grade_id = r.grade_id 
    AND g.grade NOT IN ('INC', 'INP', 'W', 'DRP')
    AND s.subjcode = r.subjcode;

您可能想在选择列表中添加一个学号。此外,如果您的 g.grade 类型比此处排除的四种类型多得多,请为此添加一列;如果少于四个,则反转子句:AND g.grade IN (...)

【讨论】:

  • Re IN vs NOT IN 优化:如果你有很多值要过滤,将它写成 VALUES 子句的连接实际上会快得多。对于NOT IN,您使用左反连接;对于IN,您使用内部连接。 (但这比原始发帖人现在想要解决的更高级的 SQL)。
  • 很好地从一个缺乏明确架构定义的问题中推断出来,顺便说一句,+1
  • 我认为使用一些子查询是必要的。谢谢。事实证明,我一直在让事情变得复杂。我实际上是在尝试计算 GPA。我已经尝试过你的代码,它就像一个魅力。所以这个查询有效SELECT r.studid, (SUM((to_number(g.grade, '9D99') * s.subjunits)))/(SUM(s.subjunits)) AS GPA FROM grade g, registration r, subject s, student t WHERE g.grade_id = r.grade_id AND g.grade NOT IN ('INC', 'INP', 'W', 'DRP') AND s.subjcode = r.subjcode AND r.studid = t.studid GROUP BY r.studid;你如何将gpa四舍五入到最接近的百分之一?
  • @oshixun:你可以把GPA投给GPA::numeric(3,2)
  • ...但最好使用带有格式说明符的to_char
【解决方案2】:

首先,请始终使用ANSI 加入。它们更具可读性。这意味着from x inner join y on (condition)而不是from x, y where condition

接下来,我认为你想要的实际上是子查询上的 join。很难说,因为您没有显示表定义或示例数据。

我认为 Patrick 的回答非常正确,指出在这种情况下您不需要子查询。这只是一个简单的三向内连接。如果您确实必须乘以从子查询派生的值,您会更像这样,在FROM 子句中使用子查询和INNER JOIN 来链接子查询,然后在@ 987654326@-list.

SELECT 
  ng.numgrade * su.subjunits
FROM
(
  SELECT 
    r.subjcode, 
    to_number(g.grade, '9D99') AS numgrade
  FROM grade g INNER JOIN registration r ON (g.grade_id=r.grade_id )
  WHERE g.grade NOT IN ('INC', 'INP', 'W', 'DRP')
) ng
INNER JOIN
(
  SELECT 
    s.subjcode,
    s.subjunits
  FROM subject s, registration r
  WHERE s.subjcode=r.subjcode
) su
ON (su.subjcode = ng.subjcode)

然而,在这种情况下,这只是帕特里克上面写的一种丑陋的方式。不需要子查询。我对帕特里克的回答所做的唯一改进是使用内部连接:

SELECT 
  g.student_id,  -- or whatever your key is
  s.subjcode,
  (to_number(g.grade, '9D99') * s.subjunits) AS product
FROM grade g
INNER JOIN registration r ON (g.grade_id = r.grade_id)
INNER JOIN subject s ON (r.subjcode = s.subjcode)
WHERE g.grade NOT IN ('INC', 'INP', 'W', 'DRP');

接受他的回答,而不是这个。

【讨论】:

  • 感谢克雷格的赞许。关于INNER JOIN 的使用:确实很难出错,因为 PG 会在格式错误的连接子句上抛出错误。但话又说回来,很容易发现笛卡尔积是WHERE 子句中缺少子句的标志。我可以将此称为个人喜好问题,还是使用INNER JOIN 对性能有好处?
  • @Patrick 没有性能差异。但是,当您编写更大的查询时,旧式连接很快就会变得难以管理。它们适用于简单的查询,但 IMO 的风格仍然很糟糕。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
  • 1970-01-01
  • 2016-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多