【问题标题】:SQL query for "concatenate on join"“连接时连接”的 SQL 查询
【发布时间】:2011-04-13 20:39:38
【问题描述】:

我正在使用 Sybase ASE 数据库。
我有两个看起来像的表:

Shops

---------------------
| ShopName | ShopID |
---------------------
| Sweetie  | 1      |
| Candie   | 2      |
| Sugarie  | 3      |
---------------------

Sweets

----------------------
| SweetName | ShopID |
----------------------
| lolly     | 1      |
| redlolly  | 1      |
| greenloly | 1      |
| taffy     | 2      |
| redtaffy  | 2      |
| bluetaffy | 2      |
| choco     | 3      |
| mintchoco | 3      |
| milkchoco | 3      |
| gummybees | 3      |
----------------------

我想编写一个查询,它会生成如下所示的结果:

-----------------------------------------------------
| ShopName | Sweets                                 |
-----------------------------------------------------
| Sweetie  | lolly, redlolly, greenlolly            |
| Candie   | taffy, redtaffy, bluetaffy             |
| Sugarie  | choco, mintchoco, milkchoco, gummybees |
-----------------------------------------------------

我该怎么做呢?我需要这个用于 Sybase ASE 数据库。我尝试了LIST() 函数,但我得到了一个错误。我查看了它的文档,发现这个功能在 ASE 版本中不可用。

这可能意味着将涉及一些“动态sql”(我不太清楚这意味着什么)。有人可以帮忙吗?

我可能希望在结果表中使用ShopId 而不是ShopName...我还不确定。我想这不会有太大的不同。此外,Sweets 结果列中的尾随逗号不是问题。我想要的只是一个非空白分隔符。

【问题讨论】:

  • 嗯听起来你想要一个字符串聚合函数。我不确定哪些数据库本身可以做到这一点,但我看到有时会看到用户定义的函数(自然会从一个 dmb 到另一个不同)。你用的是什么数据库?
  • list() 给出了什么错误?并不是说我可以帮助解决 Sybase 问题,而是其他可以识别错误消息的人。
  • 错误是没有找到LIST() 函数,这是正确的:我使用的是 Sybase ASE 版本,它没有这个函数(它的文档是这样说的)。我猜这可能需要一些 T-SQL mumbo jumbo,但我不知道该怎么做..
  • 函数LIST()仅适用于Sybase IQ,不适用于Sybase ASE

标签: sql join concatenation sap-ase


【解决方案1】:

您必须指定您使用的 DBMS。

MySQL 的GROUP CONCAT 正是您所需要的。

SELECT ShopName, GROUP_CONCAT(SweetName SEPARATOR ", ")
FROM Shops a
JOIN Sweets b
ON a.ShopID = b.ShopID
GROUP BY ShopName

【讨论】:

  • Oracle 有 wmsys.wm_concat,尽管它似乎没有记录。我自己从未使用过它,但很快就找到了。另一个使用connect by的Oracle解决方案:halisway.blogspot.com/2006/08/…
  • 我需要使用 sybase ASE 执行此操作,因此这对我不起作用... Sybase 确实有一个 LIST() 函数可以执行此操作,但 ASE 版本中没有。
  • 我的 google-fu 显示了这个链接 (projectdmx.com/tsql/rowconcatenate.aspx)。你能把它转换成我需要的 SQL 吗?
【解决方案2】:

这是一个交叉表查询,不可能在一个查询中使用 Sybase ASE。

你可以用临时表创建一个存储过程,用游标填充它,然后从这个临时表中选择。

【讨论】:

    【解决方案3】:

    我在 SQL Server 上对此进行了测试,但希望它也可以在 Sybase 上运行。如果没有,也许它会让你足够接近以解决它。

    如果我创建这个函数:

    CREATE FUNCTION SweetsList(@shopID int)
    RETURNS varchar(500)
    AS
    BEGIN
    
        DECLARE @list varchar(500)
    
        SELECT @list = COALESCE(@list+', ','') + SweetName
        FROM Sweets
        WHERE ShopID = @shopID
    
        RETURN @list
    END
    

    然后我可以执行这个查询并得到你想要的结果:

    SELECT ShopName, dbo.SweetsList(ShopID) AS Sweets
    FROM Shops
    

    希望这会有所帮助。

    【讨论】:

    • 我在这里遇到了完全相同的问题。对我来说(Sybase ASE 15.0)不起作用。由于某种原因,它只返回最后一行。这是版本依赖的东西吗?还是设置?
    【解决方案4】:

    不幸的是,adrift's 答案中的方法不适用于 Sybase ASE 的 select 语句,变量 @list 不会为每一行更新,它仅适用于最后一行。但是因为每行的更新执行和表的大小不会很大,你可以用更新语句来做。小例子:

        declare @list varchar(500)
    
        update Sweets
        set @list = @list + SweetName + ', ' 
        where ShopID = 1
    
        select SUBSTRING(@list, 1, Len(@list) - 2)
    

    附:至于我,光标不是好办法……

    【讨论】:

      【解决方案5】:

      在 Sybase ASE 中工作...

      CREATE FUNCTION SweetsList(@SN varchar(10))
      returns varchar(255)
      AS
      DECLARE @SwNList varchar(255)
      DECLARE @FetchSwN varchar(55)
      DECLARE @Status INT, @Error INT
      
      DECLARE ListCurs CURSOR FOR
      SELECT SweetName
        FROM Sweets AS SW
       JOIN Shops AS SH
        ON SH.ShopID = SW.ShopID
       WHERE SH.ShopName = @SN
      FOR READ ONLY
      
      OPEN ListCurs
      SELECT @Status = 0
      WHILE @Status = 0
      BEGIN
          FETCH ListCurs INTO @FetchSwN
      
          SELECT @Status = @@SQLSTATUS
      
          IF @Status = 0 
          BEGIN
             SELECT  @SwNList = CASE WHEN @SwNList IS NULL THEN '' ELSE @SwNList + ', ' END + @FetchSwN
          END
      END
      CLOSE ListCurs
      RETURN (@SwNList)
      go
      

      然后执行...

      SELECT ShopName, dbo.SweetsList(ShopName) AS Sweets FROM Shops
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-19
        • 2023-03-14
        • 2021-12-25
        相关资源
        最近更新 更多