Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用标准SQL连接以逗号分隔的行?_Sql_Ansi Sql - Fatal编程技术网

如何使用标准SQL连接以逗号分隔的行?

如何使用标准SQL连接以逗号分隔的行?,sql,ansi-sql,Sql,Ansi Sql,假设我们有一个表T1和一个表T2。T1和T2之间存在1:n的关系。我想选择所有T1及其所有T2,每一行对应于T2值串联的T1记录,只使用SQL标准操作 例如: T1=人 T2=受欢迎程度(按年份) 一个人每年都有一定的人气 我想使用SQL标准操作编写一个选择,结果如下: Person.Name Popularity.Value John Smith 1.2,5,4.2 John Doe NULL Jane Smith 8 其中John Smith的受欢迎程度表

假设我们有一个表T1和一个表T2。T1和T2之间存在1:n的关系。我想选择所有T1及其所有T2,每一行对应于T2值串联的T1记录,只使用SQL标准操作

例如: T1=人 T2=受欢迎程度(按年份)

一个人每年都有一定的人气

我想使用SQL标准操作编写一个选择,结果如下:

Person.Name    Popularity.Value
John Smith     1.2,5,4.2
John Doe       NULL
Jane Smith     8
其中John Smith的受欢迎程度表中有3条记录,John Doe没有记录,Jane Smith有一条记录,其值为上述值。这可能吗?怎么做


我正在使用Oracle,但希望仅使用标准SQL来完成此操作。

根据Oracle中的说明,您可以使用
listag
来实现此目标-

select t1.Person_Name, listagg(t2.Popularity_Value)
                        within group(order by t2.Popularity_Value) 
 from t1, t2
where t1.Person_Name = t2.Person_Name (+)
group by t1.Person_Name
我希望这能解决你的问题


但是你在@DavidJashi问题之后的评论。。这不是sql标准,我认为他是正确的。我也同意David的观点,在纯sql语句中无法实现这一点

这里有一种技术,使用递归公共表表达式。不幸的是,我对它的性能没有信心

我确信有一些方法可以改进这段代码,但它表明,仅仅使用SQL标准似乎并不是一种简单的方法来完成类似的事情

就我所见,确实应该有某种
STRINGJOIN
聚合函数,可以与
groupby
一起使用。这会让事情变得更容易


此查询假设存在某种连接这两个关系的
PersonID
,但是
名称也可以工作

WITH cte (id, Name, Value, ValueCount) AS (
    SELECT id,
        Name,
        CAST(Value AS VARCHAR(MAX)) AS Value,
        1 AS ValueCount
    FROM (
        SELECT ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Name) AS id,
            Name,
            Value
        FROM Person AS per
        INNER JOIN Popularity AS pop
            ON per.PersonID = pop.PersonID
    ) AS e
    WHERE id = 1

    UNION ALL

    SELECT e.id,
        e.Name,
        cte.Value + ',' + CAST(e.Value AS VARCHAR(MAX)) AS Value,
        cte.ValueCount + 1 AS ValueCount
    FROM (
        SELECT ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Name) AS id,
            Name,
            Value
        FROM Person AS per
        INNER JOIN Popularity AS pop
            ON per.PersonID = pop.PersonID
    ) AS e
    INNER JOIN cte
        ON e.id = cte.id + 1
            AND e.Name = cte.Name
)
SELECT p.Name, agg.Value
FROM Person p
LEFT JOIN (
    SELECT Name, Value
    FROM (
        SELECT Name,
            Value,
            ROW_NUMBER() OVER (PARTITION BY Name ORDER BY ValueCount DESC)AS id
        FROM cte
    ) AS p
    WHERE id = 1
) AS agg
    ON p.Name = agg.Name
这是一个示例结果:

--------------------------------
| Name        | Value          |
--------------------------------
| John Smith  | 1.2,5,4.2      |
--------------------------------
| John Doe    | NULL           |
--------------------------------
| Jane Smith  | 8              |
--------------------------------

我知道我在聚会上迟到了,但是对于其他可能发现这一点的人来说,我不相信使用纯SQL92就可以做到这一点。在过去的几个月里,我发现NetSuite试图找出哪些Oracle方法可以和哪些Oracle方法不能与他们的ODBC驱动程序一起使用,我发现他们只“支持并保证”SQL92标准

我发现了这一点,因为我需要执行listag()。一旦我发现我只能使用SQL92,我就对历史记录进行了一些挖掘,而在SQL92中根本不支持listag()和递归查询(公共表表达式)

Listag()是在Oracle SQL版本11g第2版(2009–11年前:参考)中添加的,CTE是在Oracle SQL版本9.2(2007–13年前:参考)中添加的


非常令人沮丧的是,在纯SQL92中完全不可能实现这种效果,因此在我提取了大量额外的不必要数据后,我不得不在我的C代码中解决这个问题。非常令人沮丧。

不要认为如果不使用特定于供应商的技巧,就可以在纯SQL92中实现它。想要一个只有Oracle的解决方案吗?可能与我想在Oracle中实现这一点,但要使用SQL标准操作。@DavidJashi:不可能通过递归公共表表达式实现吗?这是SQL标准,但我相信是SQL99。它通常比特定于供应商的方法慢得多。此外,这个问题的标题是如何在Oracle中将多行合并到逗号分隔的列表中?这将指定供应商。我没有指定供应商,只是在问题中添加了一个标记,表明我将在Oracle中实现这一点。但在我明确指定的问题中,我希望以一种与技术无关的方式解决这个问题,提到我希望有一个符合SQL标准的解决方案。我已经用Oracle特定的方法解决了这个问题,所以您提到的问题中的答案没有回答这个问题,所以这不是重复的问题。谢谢,这解决了问题,但它不是技术不可知的,因为您不能在任何SQL实现器技术中使用Listag,它不在SQL标准中。例如,如果我以这种方式解决问题,那么我就无法将我的项目迁移到PostgreSQL。这并不是在回答我的问题,但无论如何,我感谢您的尝试。不客气,我再次告诉您,就我所知,在纯SQL中没有可以做的工作。。。但如果您发现任何问题,请同时更新我..目前我有n+1个数据库请求,而不是一个,因为在这种情况下,仅在Oracle中工作的解决方案是不可接受的。沃伊索斯向我们保证他会给出一个解决方案,所以我在等待。同时我也在考虑这个问题,所以也许我会提供一个解决方案。我们会看到。@ LaJaSpPad:我不知道我是否会考虑我发布的“解决方案”,不幸的是,谢谢你,VoiSOS,我会尽快实现你的想法,并让你知道结果。如果它符合SQL标准并且有效,我将接受它。非常感谢。@LajosArpad:请注意性能。如果你实现了它,一定要使用真实的数据集大小进行测试。我刚刚提出了一些类似的想法,编写代码的过程向我展示了编写“数据库不可知”代码是多么毫无意义。即使是像用“from dual”创建测试数据或用“| |”、“+”或“concat”连接字符串这样简单的事情也说明了这是多么困难。太麻烦了@MikeMeyers:我同意——我认为这样的事情在应用程序代码中更容易处理。如果你真的想成为数据库不可知论者,可以使用ORM或其他某种抽象。ORA-32033:不支持的列别名32033。00000-“不支持的列别名”*原因:WITH子句中的列别名尚不受支持*操作:在定义子查询中指定别名,并在第10行“列:10”处重试错误