构造SQL查询

时间:2011-09-03 04:04:34

标签: sql oracle

我正在使用SQL和PL / SQL。

我有一个包含单列“name”的表。此列中的数据是以分号分隔的字符串。我想计算每一行中的元素数量。

例如,如果表中有两行,一行的字符串为'smith; black; tiger',另一行的字符串为'x; y',我希望第一行的查询结果为3行和第二行的2。

如何编写一个SQL查询来计算分隔的值列表中的元素数量?

2 个答案:

答案 0 :(得分:6)

您的问题很难理解,但我认为您说有一个带有“name”列的表,并且在该列中,每个单元格包含由分号分隔的多个值。您想要计算每行中以分号分隔的值的数量。

PLSQL string functions可以帮助你,但实际上你正在谈论编写程序代码来完成这项任务(这通常不是数据库查询语言的工作)。例如,您可以使用this trick来计算分号数,然后添加一个:

LENGTH(name) - LENGTH(TRANSLATE(name,'x;','x')) + 1

但@Johan提出的观点是,这是构建数据的一种糟糕方式。例如,它使得无法正确查找名称。您不能说where name == "smith",因为名称不等于"smith",它等于"smith;black;tiger"。您将不得不进行子字符串搜索,说where name like "smith",这将是低效和错误的。如果我要求查找名称“smi”怎么办?你会说where name like "smi"会错误地找到那个结果 - 没有办法说“smith”在表中但是“smi”不是,因为两者都是“smith; black; tiger”的子串

如果您希望条目具有多个名称,那么更好的解决方案是为条目提供唯一ID;比如说123.(你可以要求SQL自动为表行生成唯一的ID。)然后,有一个单独的表,用于映射回该行的名称。所以说你给了“smith; black; tiger”行ID 123和“x; y”行ID 124.现在你将有另一个表NameMap有两列:

name    |  entry
------------------
smith   |   123
black   |   123
tiger   |   123
x       |   124
y       |   124

现在,您可以在该表中查找名称,并使用连接将它们映射到名称条目表。

你将能够回答你的问题:“有多少名字对应于条目表的每一行”,并带有GROUP BY语句,如下所示:

SELECT name, count(*) as value_count FROM NameMap GROUP BY name

答案 1 :(得分:4)

您可以使用此代码破解此

SQL code horror

SELECT name
       ,(LENGTH(COALESCE(vals,'')) 
        - LENGTH(TRANSLATE(COALESCE(vals,''), ';',''))) + 1 AS value_count
FROM table1
ORDER BY name

<强>说明
数据库中的CSV是一种非常糟糕的反模式 VALUES是保留字,在保留字后命名列是个坏主意。