通过 SQL 根据日期合并(连接)行
Combine(concatenate) rows based on dates via SQL
我有以下 table.
Animal Vaccine_Date Vaccine
Dog 1/1/2016 x
Dog 2/1/2016 y
Dog 2/1/2016 z
Cat 2/1/2016 y
Cat 2/1/2016 z
我希望能够将同一动物和同一日期的疫苗结合起来,以便它们出现在同一细胞中。下面的 table 是期望的最终结果。
Animal Vaccine_Date Vaccine
Dog 1/1/2016 x
Dog 2/1/2016 y,z
Cat 2/1/2016 y,z
我试图创建一个 volatile table 来这样做,但我没有任何运气,我认为 Teradata 无法识别 Group_concat.
你可以使用这个查询,
SELECT
Animal,Vaccine_Date,
LISTAGG(Vaccine, ',') WITHIN GROUP (ORDER BY Vaccine) "names"
FROM table_name
GROUP BY Vaccine
希望你明白了
试试这个。 STUFF 函数非常适合这种情况:
SELECT
Animal, Vaccine_Date,
STUFF(
(SELECT DISTINCT ',' + Vaccine
FROM TableName
WHERE Animal = a.Animal AND Vaccine_Date = a.Vaccine_Date
FOR XML PATH (''))
, 1, 1, '') AS VaccineList
FROM TableName AS a
GROUP BY Animal, Vaccine_Date
更新 20180419
Teradata(不确定是哪个版本)添加了 XMLAGG,这将是比递归更好的选择)
原回答:
Teradata 没有 group_concat
/listagg
功能。有几个解决方法。我最喜欢的是使用递归 CTE。它不是非常有效,但它有很好的文档记录和支持的功能。
你的情况:
WITH RECURSIVE recCTE AS
(
SELECT
Animal,
Vaccine_Date,
CAST(min(Vaccine) as VARCHAR(50)) as vaccine_list, --big enough to hold concatenated list
1 as depth, --used to determine the largest/last group_concate (the full group) in the final SELECT
Vaccine
FROM table
GROUP BY 1,2
UNION ALL
SELECT
recCTE.Animal,
recCTE.Vaccine_Date,
recCTE.Vaccine || ',' || table.Vaccine
recCTE.depth + ,
table.Vaccine
FROM recCTE
INNER JOIN table ON
recCTE.Animal = table.Animal AND
recCTE.Vaccine_Date = Table.Vaccine_Date
table.vaccine > recCTE.vaccine
)
--Now select the result with the largest depth for each animal/vaccine_date combo
SELECT * FROM recCTE
QUALIFY ROW_NUMBER() OVER (PARTITION BY animal,vaccine_date ORDER BY depth desc) = 1
您可能需要稍微调整一下(可能 trim 连接之前的疫苗值等等),但它应该能让您大致了解。您可以查看递归 CTE 文档 at this link,但它非常枯燥。如果您不熟悉,那里也有很多教程。 Teradata 的递归 CTE 实现与 T-SQL 和 PostgresSQL 的实现非常相似。
作为另一种选择,您可以查看尚未记录的 tdstats.udfconcat()
,正如 Teradata 社区网站 this thread 中知识渊博的@dnoeth 所解释的那样。
我有以下 table.
Animal Vaccine_Date Vaccine
Dog 1/1/2016 x
Dog 2/1/2016 y
Dog 2/1/2016 z
Cat 2/1/2016 y
Cat 2/1/2016 z
我希望能够将同一动物和同一日期的疫苗结合起来,以便它们出现在同一细胞中。下面的 table 是期望的最终结果。
Animal Vaccine_Date Vaccine
Dog 1/1/2016 x
Dog 2/1/2016 y,z
Cat 2/1/2016 y,z
我试图创建一个 volatile table 来这样做,但我没有任何运气,我认为 Teradata 无法识别 Group_concat.
你可以使用这个查询,
SELECT
Animal,Vaccine_Date,
LISTAGG(Vaccine, ',') WITHIN GROUP (ORDER BY Vaccine) "names"
FROM table_name
GROUP BY Vaccine
希望你明白了
试试这个。 STUFF 函数非常适合这种情况:
SELECT
Animal, Vaccine_Date,
STUFF(
(SELECT DISTINCT ',' + Vaccine
FROM TableName
WHERE Animal = a.Animal AND Vaccine_Date = a.Vaccine_Date
FOR XML PATH (''))
, 1, 1, '') AS VaccineList
FROM TableName AS a
GROUP BY Animal, Vaccine_Date
更新 20180419
Teradata(不确定是哪个版本)添加了 XMLAGG,这将是比递归更好的选择)
原回答:
Teradata 没有 group_concat
/listagg
功能。有几个解决方法。我最喜欢的是使用递归 CTE。它不是非常有效,但它有很好的文档记录和支持的功能。
你的情况:
WITH RECURSIVE recCTE AS
(
SELECT
Animal,
Vaccine_Date,
CAST(min(Vaccine) as VARCHAR(50)) as vaccine_list, --big enough to hold concatenated list
1 as depth, --used to determine the largest/last group_concate (the full group) in the final SELECT
Vaccine
FROM table
GROUP BY 1,2
UNION ALL
SELECT
recCTE.Animal,
recCTE.Vaccine_Date,
recCTE.Vaccine || ',' || table.Vaccine
recCTE.depth + ,
table.Vaccine
FROM recCTE
INNER JOIN table ON
recCTE.Animal = table.Animal AND
recCTE.Vaccine_Date = Table.Vaccine_Date
table.vaccine > recCTE.vaccine
)
--Now select the result with the largest depth for each animal/vaccine_date combo
SELECT * FROM recCTE
QUALIFY ROW_NUMBER() OVER (PARTITION BY animal,vaccine_date ORDER BY depth desc) = 1
您可能需要稍微调整一下(可能 trim 连接之前的疫苗值等等),但它应该能让您大致了解。您可以查看递归 CTE 文档 at this link,但它非常枯燥。如果您不熟悉,那里也有很多教程。 Teradata 的递归 CTE 实现与 T-SQL 和 PostgresSQL 的实现非常相似。
作为另一种选择,您可以查看尚未记录的 tdstats.udfconcat()
,正如 Teradata 社区网站 this thread 中知识渊博的@dnoeth 所解释的那样。