添加新列,其中 CONCAT 的过去期间(日期范围)的值与 SQL 中的组有关
Add new column that CONCAT's values from past period (date range) respecting groups in SQL
我正在使用 MS SQL Server 2012 检查用户是否在过去一段时间内为每个 transaction/row.
选择了特定类型的电影
我想解决这个问题,方法是将过去的类型在给定时间段内连接到一个新列中,例如过去 12 个月,或 6 至 12 个月。我不关心新专栏中出现的重复类型。
然后我可以 运行 逻辑来检查特定类型是在 SQL 中还是由外部程序订购的。下面是两个订购视频的客户的预期输出示例。
这里是我用来生成初始table的SQL。
DROP TABLE IF EXISTS tb1;
CREATE TABLE tbl
(id int IDENTITY(1,1) PRIMARY KEY,
PersonName VARCHAR(10),
OrderDT DATETIME,
Genre VARCHAR(10));
INSERT INTO tbl (PersonName, OrderDT, Genre)
VALUES
('Bob', '2019-05-01', 'biopic'),
('Bob', '2019-10-01', 'drama'),
('Bob', '2020-02-01', 'doco, action' ),
('Bob', '2020-05-01', 'comedy'),
('Bob', '2020-09-01', 'horror'),
('Bob', '2020-12-01', 'action, comedy'),
('Alice', '2018-03-01', 'comedy, drama'),
('Alice', '2018-08-01', 'action'),
('Alice', '2018-12-01', 'horror');
我知道使用 STRING_AGG() 和 GROUP BY 可用于聚合每个客户的值行,但我需要帮助才能在过去一段时间和每一行中执行此操作。
即使我使用的是 MS SQL(我自己没有选择 :))我希望该解决方案足够通用,可以在 Postgres 或 MariaDB 中使用。因此,如果可能,我想避免使用特殊的 MS SQL 服务器专用命令,例如 STRING_AGG()。
这个问题在 SQL 服务器中已经够难的了。您不应该在一个字符串中存储多个流派。你提到 string_agg()
所以你显然没有使用 SQL Server 2012。这是在 SQL Server 的更新版本中工作的逻辑:
select t.*, t12.*, t6.*
from tbl t cross apply
(select string_agg( trim(g.genre), ', ') as orders_12mon
from (select distinct s.value as genre
from tbl t2 cross apply
string_split(genre, ',') s
where t2.personname = t.personname and
t2.orderdt <= t.orderdt and
t2.orderdt > dateadd(month, -12, t.orderdt)
) g
) t12 cross apply
(select string_agg( trim(g.genre), ', ') as orders_6mon
from (select distinct s.value as genre
from tbl t2 cross apply
string_split(genre, ',') s
where t2.personname = t.personname and
t2.orderdt > dateadd(month, -12, t.orderdt) and
t2.orderdt <= dateadd(month, -6, t.orderdt)
) g
) t6;
Here 是一个 db<>fiddle.
此代码是高度不可移植的。以下是一些原因:
- Date/time函数在不同的数据库中是不同的。没有一致的方法可以在您提到的数据库中减去 6 个月。
- SQL 服务器不支持带时间间隔的
range
关键字。
- 不同数据库的字符串处理函数差异很大,所以拆分字符串并不标准。
就是说,如果您事先了解所有类型,我可以想出一种神秘的方法。但这真的很乱,你提到的每个数据库中都有更简单的方法。
我正在使用 MS SQL Server 2012 检查用户是否在过去一段时间内为每个 transaction/row.
选择了特定类型的电影我想解决这个问题,方法是将过去的类型在给定时间段内连接到一个新列中,例如过去 12 个月,或 6 至 12 个月。我不关心新专栏中出现的重复类型。
然后我可以 运行 逻辑来检查特定类型是在 SQL 中还是由外部程序订购的。下面是两个订购视频的客户的预期输出示例。
这里是我用来生成初始table的SQL。
DROP TABLE IF EXISTS tb1;
CREATE TABLE tbl
(id int IDENTITY(1,1) PRIMARY KEY,
PersonName VARCHAR(10),
OrderDT DATETIME,
Genre VARCHAR(10));
INSERT INTO tbl (PersonName, OrderDT, Genre)
VALUES
('Bob', '2019-05-01', 'biopic'),
('Bob', '2019-10-01', 'drama'),
('Bob', '2020-02-01', 'doco, action' ),
('Bob', '2020-05-01', 'comedy'),
('Bob', '2020-09-01', 'horror'),
('Bob', '2020-12-01', 'action, comedy'),
('Alice', '2018-03-01', 'comedy, drama'),
('Alice', '2018-08-01', 'action'),
('Alice', '2018-12-01', 'horror');
我知道使用 STRING_AGG() 和 GROUP BY 可用于聚合每个客户的值行,但我需要帮助才能在过去一段时间和每一行中执行此操作。
即使我使用的是 MS SQL(我自己没有选择 :))我希望该解决方案足够通用,可以在 Postgres 或 MariaDB 中使用。因此,如果可能,我想避免使用特殊的 MS SQL 服务器专用命令,例如 STRING_AGG()。
这个问题在 SQL 服务器中已经够难的了。您不应该在一个字符串中存储多个流派。你提到 string_agg()
所以你显然没有使用 SQL Server 2012。这是在 SQL Server 的更新版本中工作的逻辑:
select t.*, t12.*, t6.*
from tbl t cross apply
(select string_agg( trim(g.genre), ', ') as orders_12mon
from (select distinct s.value as genre
from tbl t2 cross apply
string_split(genre, ',') s
where t2.personname = t.personname and
t2.orderdt <= t.orderdt and
t2.orderdt > dateadd(month, -12, t.orderdt)
) g
) t12 cross apply
(select string_agg( trim(g.genre), ', ') as orders_6mon
from (select distinct s.value as genre
from tbl t2 cross apply
string_split(genre, ',') s
where t2.personname = t.personname and
t2.orderdt > dateadd(month, -12, t.orderdt) and
t2.orderdt <= dateadd(month, -6, t.orderdt)
) g
) t6;
Here 是一个 db<>fiddle.
此代码是高度不可移植的。以下是一些原因:
- Date/time函数在不同的数据库中是不同的。没有一致的方法可以在您提到的数据库中减去 6 个月。
- SQL 服务器不支持带时间间隔的
range
关键字。 - 不同数据库的字符串处理函数差异很大,所以拆分字符串并不标准。
就是说,如果您事先了解所有类型,我可以想出一种神秘的方法。但这真的很乱,你提到的每个数据库中都有更简单的方法。