【问题标题】:SQL SELECT DISTINCT but combine results from another tableSQL SELECT DISTINCT 但合并来自另一个表的结果
【发布时间】:2012-09-04 23:56:39
【问题描述】:

我什至不确定要搜索什么,如果这已经在某个地方覆盖,请原谅我。

我有一个从多个表中提取数据的 SELECT 语句。正如预期的那样,如果我运行这个查询,我会得到第二个表中每条记录的记录,如下所示。

|ID     |Name     |Assets
 ------------------------------------
|1      |Bob      |Car
|1      |Bob      |Bicycle
|1      |Bob      |House
|2      |Jane     |Car
|2      |Jane     |House
|3      |Peter    |Boat
|3      |Peter    |Car
|3      |Peter    |Motorcycle

我想要的是这样的:

|ID     |Name     |Assets
 ------------------------------------
|1      |Bob      |Car,Bicycle,House
|2      |Jane     |Car,House
|3      |Peter    |Boat,Car,Motorcycle

我已经能够使用 PHP 实现这一点,只需为我从第一个表中获得的每条记录再次访问数据库,但这使我的页面变慢,因为它每次页面刷新访问数据库大约 40-60 次.

查询 1:

SELECT ID,Name FROM People

然后在while循环中查询2:

<?php
while($owner_row=odbc_fetch_array($query1) {
$assets = odbc_exec($conn,"SELECT Asset FROM Assets WHERE Owner='$owner_row[Name]'");
$asset_array = odbc_fetch_array($assets);
$asset_string = implode(",",$asset_array);
}

然后,我可以将来自每个所有者的资产结果组合成一个字符串,并根据需要显示它们。

有没有办法在单个查询中实现这一点,以便我只访问数据库一次并以某种方式将这些资产组合成查询本身中的单个值?

【问题讨论】:

标签: php sql select odbc sybase


【解决方案1】:

请使用以下 SQL:

declare @tempUser  Table
(
ID int,
Name nvarchar(250),
AssetNAme nvarchar(250)
)
Insert into @tempUser values(1,'Bob','Car')
Insert into @tempUser values(1,'Bob','Bicycle')
Insert into @tempUser values(1,'Bob','House')
Insert into @tempUser values(2,'Jane','Car')
Insert into @tempUser values(2,'Jane','House')
Insert into @tempUser values(3,'Peter','Boat')
Insert into @tempUser values(3,'Peter','Car')
Insert into @tempUser values(3,'Peter','MotorCycle')


select  tt.ID,tt.Name,(select ITT.AssetNAme + ', ' as 'data()'  from @tempUser as ITT 
where ITT.ID =tt.ID for xml path('')) from @tempUser  as tt group by tt.ID,tt.Name

【讨论】:

  • 它在sybase而不是sql server
【解决方案2】:

在此处使用 Sybase LIST 函数。

例如

SELECT ID,NAME,LIST(ASSETS)
FROM PEOPLE
GROUP BY ID,NAME

【讨论】:

  • 嗨,Niladri,通过一个相当简单的查询,我得到“警告:odbc_exec() [function.odbc-exec]:SQL 错误:[DataDirect][ODBC Sybase Wire Protocol driver][SQL Server]Function未找到‘列表’。”所以我正在访问的数据库可能存在版本问题。我将尝试一些其他方法(改变设计等以不同的方式处理数据)并且暂时让这个方法进入休眠状态。感谢您的帮助。
【解决方案3】:

我不确定您要访问哪个数据库,但如果您使用的是 mySQL,有一个可爱的函数可以执行此操作,称为 group_concat,其工作原理如下:

select 
    a.ID, 
    a.Name, 
    group_concat(b.Asset) as assetGroup 
from 
    people a
        join Assets b
            on a.ID=b.Owner 
group by 
    a.ID, 
    a.Name

这会完全输出:

|ID     |Name     |Assets
 ------------------------------------
|1      |Bob      |Car,Bicycle,House
|2      |Jane     |Car,House
|3      |Peter    |Boat,Car,Motorcycle

编辑:我假设 people 表中的每条记录在 Assets 表中至少有一个匹配记录 - 如果没有,请在查询中使用外连接。

编辑:我不熟悉 SyBase,但快速搜索相关函数给了我一个坏消息:MYSQL group_concat equivalent in Sybase ASE? SyBase 中没有这样的函数,您必须编写一个存储过程来获取结果,但它表明您仍然可以直接在数据库上执行此操作(尽管方式要困难得多)。

如果您不想编写存储过程,您仍然可以在查询中连接表,然后简单地将每个 ID 的许多行返回到 PHP 中,然后按照以下行简单地循环它们:

$currentID=0;
$userAssets=array();
while($row=$AnotherRowFromTheDatabase)
{
    if($row['ID']==$currentID)
    {
        $userAssets[]=$row['Asset'];
    }
    else
    {
        $currentID=$row['ID'];
        // More stuff to move the array previously
        // and start a new Assets Array
    }
}

【讨论】:

  • 他实际上是从两个表中抓取数据
  • @DavidFaber 如果他还在打mysql,他可以很好地在多表查询中使用该功能。然而,我已经更新了查询以使用他描述的表结构。
  • 大家好,如上所述。它是通过 ODBC 连接的 Sybase。
  • 好的,谢谢 Fluffeh。在这种情况下,我可能会坚持使用我的慢速 PHP 解决方案。感谢您的尝试。 :)
  • @Barbs 我给了你一个(可能)比刚才在我的编辑中对数据库进行 40-60 次查询要快得多的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 2019-04-20
  • 2021-02-08
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多