【问题标题】:issue on database query to fetch data with subquery数据库查询问题以使用子查询获取数据
【发布时间】:2015-03-16 19:27:01
【问题描述】:

我在使用 SELECT 查询时遇到问题。

    SELECT P.product_id
          , ( SELECT Category_id 
              FROM   Category C 
              WHERE  C.product_id = P.product_id) AS cat
    FROM Products P

这应该从 PRODUCTS 中提取 product_id,从 CATEGORY 中提取 category_id。如果产品属于多个类别,我希望类别字段返回这些类别 ID 的列表。问题是子查询只会返回一个值。有谁知道如何重写这个?

谢谢!

【问题讨论】:

  • 您遇到的问题是 mysql 还是 sql-server?
  • 我需要 sql 查询逻辑方面的帮助才能使用子查询获取列表。我将同时使用 mssql 和 mysql 数据库。

标签: mysql sql-server


【解决方案1】:

为此使用GROUP_CONCAT

 SELECT P.product_id,  GROUP_CONCAT(PC.category_id SEPARATOR ', ')
   FROM Product_Category PC ,
        Products P
  WHERE PC.product_id = P.product_id
  GROUP BY P.product_id;

查看this Fiddle

【讨论】:

  • 谢谢,这就是我想要的:)
  • GROUP_CONCAT() 是一个 MySQL 函数,因此您必须使用 MS SQL 中的 STUFF() 函数。而且我一直发现使用显式 JOIN 语句更具可读性(没有性能差异):FROM Product_Category PC INNER JOIN Products P ON PC.product_id = P.product_id。
  • @Shawn: 给出了两个标签,mysqlsql-server,当这个答案得到时,我正要创建一个 MS 版本被 OP 接受。
  • @Trinimon 我喜欢 GROUP_CONCAT()。这是我多年来在 MS SQL 中不得不做的事情。我知道这两个函数都采用 SQL 风格已经有一段时间了,但它们仍然可能是我见过的更常见的操作之一。获取关系数据很容易,但有时您只需要与特定值关联的另一个数据列表。 :-)
  • 请务必注意分隔符。逗号让我对字符数据类型字段感到抓狂。 :-S
【解决方案2】:

Select 中的子查询必须返回标量值,否则会出错。您可以连接两个表以获取多个值。或者您可以使用 TOP 子句强制子查询只返回一个值。

试试

SELECT P.product_id
      ,PC.Category_id AS Categories
FROM Products P
INNER JOIN Product_Category PC ON PC.product_id = P.product_id

SELECT P.product_id
     , (SELECT TOP 1 Category_id 
        FROM Product_Category PC 
        WHERE PC.product_id = P.product_id
        ORDER BY PC.SomeColumn ) AS Categories
FROM Products P

【讨论】:

  • 我想从不同的表中获取产品 ID 和多个类别 ID 的一行。
  • 他们只是坚持连接查询,你不能在选择中使用子查询。
【解决方案3】:

您有几个选择,其中包括:

select p.PRODUCT_ID, CATEGORY_ID
FROM products p
inner join product_category pc on p.product_id = pc.product_id

这将为每个 product_Id 和 category_id 组合返回一行。

另一个选项(仅限 Sql server 2005+)

SELECT p.product_id, 
STUFF((
  SELECT ','+ convert(varchar(50), pc.category_id) 
  FROM product_category pc 
  WHERE pc.product_id = p.product_id 
  FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '') 
FROM products p

这将为每个产品 ID 创建一个以逗号分隔的类别 ID 列表。见:http://sqlfiddle.com/#!6/303e7d/1

看起来已经为完成mysql版本提供了答案

【讨论】:

  • 这会报错ambiguous column product_id
  • 您不需要 STUFF() 中的 WHERE。这是在 JOIN 中完成的。相反,您实际上并不需要 STUFF() 中的 JOIN。
  • SELECT p.product_id, STUFF((SELECT ','+ convert(varchar(50), pc.category_id) FROM product_category pc WHERE pc.product_id = p.product_id FOR XML PATH('') , TYPE).value('.','VARCHAR(max)'), 1, 1, '') FROM products p
  • @Shawn 谢谢,更新了我的答案 - 这肯定更短,而且由于不必要的东西,我确信性能更高 - 呃......事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
相关资源
最近更新 更多