【问题标题】:Can't get the name of a related table column无法获取相关表列的名称
【发布时间】:2020-10-10 05:57:15
【问题描述】:

我刚刚开始学习 SQL,到目前为止(从两天前开始)我设法解决了我的大部分问题,但现在我需要帮助。

下面的查询产生 1 列和 1 行:“12345”和一些额外的值为 0 的行,我需要删除它们。

SELECT product_id FROM sale_order_line WHERE order_id IN (SELECT id FROM sale_order WHERE name='S00062')

所以我尝试了以下方法:

SELECT product_id FROM sale_order_line WHERE order_id IN (SELECT id FROM sale_order WHERE name='S00062') AND NOT product_id='0'

现在我得到了我期待的结果“12345”。 但是当我尝试从另一个表中获取与“12345”相关的列的名称时......:

SELECT name FROM product_template WHERE product_variant_ids IN (SELECT product_id FROM sale_order_line WHERE order_id IN (SELECT id FROM sale_order WHERE name='S00062') AND NOT product_id='0')

我收到一条错误消息:“无法将整数的数据类型与字符串进行比较”。 不知何故,上面的代码似乎试图在所有 0 被删除之前读取 product_id。我猜。

但是,如果我直接这样做,比如:

SELECT name FROM product_template WHERE product_variant_ids = '12345'

有效! 我怎样才能解决这个问题? 请原谅我的新手编码技能。

【问题讨论】:

  • 如有此类问题,请提供您的 Postgres 版本和基本表定义(CREATE TABLE 显示数据类型和约束的语句)。
  • 感谢您的回复。我实际上不知道我的 postgresql 版本。我可以从 SQL 中检查它吗?我正在访问我公司的 ERP (ODOO) 在线版本,我刚刚开始了解数据库结构,我需要从 ERP 本身中提取一些我无法提取的数据。所以我正在使用 Python 连接器。所以基本上我需要从我不知道的数据库中提取数据,使用我也不知道的编程语言......
  • 询问 Postgres:SELECT version();
  • 返回未知函数版本。
  • No Postgres 版本会这么说。看起来您正在使用不同的 RDBMS。

标签: sql postgresql database-design types


【解决方案1】:

product_template.product_variant_idssale_order_line.product_id 似乎是不兼容的数据类型,integer 之一是字符串类型(textvarchar、...) - 正如错误消息所示.

养成在涉及多列的查询中对所有列名进行表限定的习惯。

从列名猜测,product_idinteger,而product_variant_ids 是字符串类型,这很可能是设计错误。如果它实际上在字符串表示中包含一个有效整数,就像您的最终查询所暗示的那样,然后在您的数据模型中对 PK 约束做出更多假设,您的查询可以像这样工作:

SELECT pt.name
FROM   sale_order       so
JOIN   sale_order_line  sol ON sol.order_id = so.id
JOIN   product_template pt  ON pt.product_variant_ids::int = sol.product_id  -- !
WHERE  so.name = 'S00062'
AND    NOT sol.product_id = 0;  -- numeric literal without 

注意转换为整数:product_variant_ids::int。但这只是给猪涂口红。该列应以 integer 开头。

然后,名称product_variant_ids 表示多个值,暗示int[],一个整数数组。那么你需要做更多的事情......

使用JOIN 表示法,而不是嵌套多个级别的x IN (subquery)。更简单,通常更快。

只要子查询返回不同的值,两者都是相同的。否则,IN 表示法会折叠重复项,而连接则不会。这种差异也使x IN (subquery) 内部执行更加复杂,因此成本更高。

最后,名为product_variant_ids 的列通常表示在任何情况下都存在错误的数据库设计。通常,您不会在单个列中填充多个值。如果该列上面有一个字符串类型,那就是双重禁忌。您必须进一步研究关系设计和数据库规范化。

【讨论】:

  • 我仍在理解你的代码:) 但是,虽然我对 SQL 知之甚少,但我同意你的理解。我在其他查询中使用了 JOIN 表示法,但我发现“阅读”更令人困惑。而且由于我每次只能使用一个查询,所以我使用了子查询。但我下次会做得更好。我认为连接器的限制将是最大的问题。当我现在运行您的脚本时,出现错误:“表 'product_template' 的列名 'product_variant_ids::int' 无效。”
  • @Telmo:同样,不是 Postgres 错误消息。这是 Postgres 特定的强制转换语法。请参阅:stackoverflow.com/a/13676871/939860 尝试使用标准 SQL ON cast(pt.product_variant_ids AS integer) = sol.product_id。但在继续之前找出您正在处理的确切 RDBMS 和版本。这样没有意义...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 2021-10-19
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多