【问题标题】:SQL: Basics on JOINs and other tablesSQL:关于 JOIN 和其他表的基础知识
【发布时间】:2011-12-13 17:06:25
【问题描述】:

我想我需要一个提示,往哪个方向走。 跟进我的other question,我正在尝试使用 MySQL 对 3 个表执行 sql 查询。

表 1:产品的“基础”信息

id, productnumber
1,45

表 2:每个产品 ID 的“country_specifics”

id, countrycode,name
1,"DE","Produkt 1"
1,"US","Product 1"

好的,一个

SELECT B.id,C.name,C.countrycode 
FROM base AS B 
INNER JOIN country_specifics AS C ON B.id=C.id
WHERE B.id=1 AND C.countrycode='US';

给我我想要的:

1,"Product 1","US"

但是:

我有第三张桌子:

表 3:每个产品 ID 的“功能”

id,feature
1,"feature 1"
1,"feature 2"

我的查询的最终结果应该以某种方式额外包含产品具有的功能。 我尝试了一个额外的

INNER JOIN features AS F ON b.id=f.id

但这将返回两行(我明白为什么):

1,"Product 1","US","feature 1"
1,"Product 1","US","feature 2"

但我认为这不是我想要的。 我想要的是特征字段的一种数组:

1,"产品 1","US","功能 1,功能 2"

结果。我知道(或相当肯定)SQL 中没有数组,但最接近的呢?我可以在 1 个查询中做到这一点吗?显然,我可以简单地开始第二个查询,但这是最好的选择吗? 我应该搜索哪个关键字?

感谢阅读,马林巴琴

编辑

谢谢大家的帮助,真的!

我只是想澄清我的问题:我不一定需要数组或类似的东西。我想了解获取“该产品的所有数据”的最佳(最有效、最不容易出错)方法是什么。

如果您告诉我接受 2 行作为结果并使用这是最好的方法,我会这样做。 我只是认为他们在设计 SQL 时就想到了这个问题并准备好了解决方案,而我正在努力寻找那个解决方案。

编辑 2:

再次,我很抱歉误导人们认为我需要一个逗号分隔的字符串。我试图说明我期待什么样的数据。

我很欣赏指向 group_concat 的指针,但我觉得 stored procedure 有 2 个查询,如 jmacinnes 和 Sachin 所述,是更清洁的方式。

谢谢你,stackoverflow 社区。​​p>

【问题讨论】:

  • 这适用于 Sybase ASE、SQL Server、Oracle、MYSQL?
  • mysql - 来自第一段第二句。
  • @marimba - 你使用 MySQL 吗? (不同风格的 SQL 有不同的方法来解决这个问题。)
  • 是的,MySQL。我现在加粗了。我以为没那么重要,但我开始明白没有标准的解决方案。

标签: mysql sql join multiple-tables


【解决方案1】:

您可以编写一个函数或一个存储过程,它接受一个 id,然后为 features 表返回一个字符串,其中包含具有该 id 的所有功能。然后您可以在原始查询中使用它。

【讨论】:

    【解决方案2】:

    我认为您应该使用您已经编写的单个查询来执行此操作。然后,只需格式化该数据以在应用程序层中以您想要的方式显示。您可以遍历结果并将每个产品的所有功能组合在一起。

    虽然可以返回您所追求的结果集,但这样做是一种不好的做法。如果将来要更改特征表,这将使解析数据变得更加困难。

    如果您通过加入 Features 表获得的重复数据很重要,那么您可以在一个存储过程中返回两个结果集:

    SELECT B.id,C.name,C.countrycode 
    FROM base AS B 
    INNER JOIN country_specifics AS C ON B.id=C.id
    WHERE B.id=1 AND C.countrycode='US';
    
    SELECT id featureId FROM features where ProductId = 1
    

    【讨论】:

    • 我想知道这一点:假设产品 1 有 25 个功能。这将导致 25 行,其中 24 行仅用于功能 ID。就带宽、内存、循环而言,这不是效率低下吗?
    • 从 CPU 的角度来看,我怀疑直接返回数据会比在数据库上连接数据要快。数据库不太擅长字符串解析。此外,它将负载推送到您的数据库,这可以在应用程序层轻松完成。一般来说,扩展网络服务器比扩展数据库要容易得多。在带宽方面,如果您要返回大量在产品行之间重复的数据,您可以更改单个存储过程以返回多个结果集。
    • 是的,恐怕这将是各种产品和功能的大量数据。您能否详细说明“更改单个存储过程以返回多个结果集”?我不明白...
    • 好的,知道了,谢谢!因此,使用 2 个查询(尽管是组合的)是 SQL 方式。我想这就是我想知道的。
    【解决方案3】:

    因为你使用的是MySQL,所以可以使用group_concat:

    SELECT B.id,C.name,C.countrycode, group_concat(F.feature) as feature_list 
    FROM base AS B 
    INNER JOIN country_specifics AS C ON B.id=C.id
    WHERE B.id=1 AND C.countrycode='US'
    INNER JOIN features AS F ON B.id=F.id
    GROUP BY B.id
    

    【讨论】:

    • 这就是为什么我说“因为您使用的是 MySQL”——请参阅问题第一段中的第二句话。
    • 我刚刚为 group_concat 找到了一个很好的例子,而作者正是我遇到的问题,所以看来这是要走的路……尽管我想知道。不过非常感谢您的帮助!
    【解决方案4】:

    以下解决方案是基于 Oracle 的,您可以尝试在 MySQL 中实现相同的解决方案

    你可以创建如下的数据库函数

    create or replace function prod_feature(p_product_id in number) return varchar2
        v_feature varchar2(2000) := '';
        i number := 0 ;
    begin
        for c1rec in (select feature from table3 where product_id = p_product_id) loop
           if i = 0 then
               v_feature:= v_feature|| c1rec.feature;
           else
               v_feature:= v_feature|| ', ' || c1rec.feature;
           end if;
           i  := i +1;
        end loop;
        return v_feature;
    end; 
    

    然后在第一个sql中使用这个函数

    SELECT B.id,C.name,C.countrycode, prod_feature(id) 
    FROM base AS B 
    INNER JOIN country_specifics AS C ON B.id=C.id
    WHERE B.id=1 AND C.countrycode='US';
    

    【讨论】:

    • 您可以在输入代码时使用{} 按钮将其格式化为代码 - 我已经修改了您的答案以为您格式化代码。
    【解决方案5】:

    这个怎么样。试试这个,看看它是否按你想要的方式工作。

    SELECT id, name, code, GROUP_CONCAT(fea) features FROM 
    (  
      SELECT id, name, code, f.feature fea FROM 
      (
        SELECT b.id id, cs.name name, cs.countrycode code FROM 
        base b
        JOIN country_specifics cs
        ON cs.id = b.id
        AND cs.countrycode = "US"
       ) a
     JOIN features f
     ON f.id = a.id  
    ) b
    GROUP BY id
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 2012-05-12
      • 2012-07-29
      • 1970-01-01
      • 2010-09-26
      • 1970-01-01
      相关资源
      最近更新 更多