为什么以下查询返回无限行?我本来希望该EXCEPT条款终止递归..
with cte as (
select *
from (
values(1),(2),(3),(4),(5)
) v (a)
)
,r as (
select a
from cte
where a in (1,2,3)
union all
select a
from (
select a
from cte
except
select a
from r
) x
)
select a
from r
Run Code Online (Sandbox Code Playgroud)
这是我的 C# homeworld 中的一种微不足道的任务,但我还没有在 SQL 中实现它,并且更愿意基于集合(没有游标)解决它。结果集应该来自这样的查询。
SELECT SomeId, MyDate,
dbo.udfLastHitRecursive(param1, param2, MyDate) as 'Qualifying'
FROM T
Run Code Online (Sandbox Code Playgroud)
它应该如何工作
我将这三个参数发送到 UDF 中。
UDF 在内部使用参数从视图中获取相关 <= 90 天之前的行。
UDF 遍历“MyDate”并返回 1(如果它应该包含在总计算中)。
如果不应该,则返回 0。此处称为“合格”。
udf 会做什么
按日期顺序列出行。计算行之间的天数。结果集中的第一行默认为 Hit = 1。如果差异达到 90,则传递到下一行,直到差距总和为 90 天(必须通过第 90 天)到达时,将 Hit 设置为 1 并将差距重置为 0 . 它也可以代替结果中的行。
|(column by udf, which not work yet)
Date Calc_date MaxDiff | Qualifying
2014-01-01 11:00 2014-01-01 0 | 1
2014-01-03 10:00 2014-01-01 2 | 0
2014-01-04 09:30 2014-01-03 1 | 0
2014-04-01 10:00 …Run Code Online (Sandbox Code Playgroud) 从其他编程语言转向 SQL,递归查询的结构看起来很奇怪。一步步走过来,仿佛分崩离析。
考虑以下简单示例:
CREATE TABLE #NUMS
(N BIGINT);
INSERT INTO #NUMS
VALUES (3), (5), (7);
WITH R AS
(
SELECT N FROM #NUMS
UNION ALL
SELECT N*N AS N FROM R WHERE N*N < 10000000
)
SELECT N FROM R ORDER BY N;
Run Code Online (Sandbox Code Playgroud)
让我们来看看吧。
首先,执行锚成员并将结果集放入 R。因此 R 被初始化为 {3, 5, 7}。
然后,执行低于 UNION ALL 并且第一次执行递归成员。它在 R 上执行(即,在我们目前手头的 R 上:{3, 5, 7})。这导致 {9, 25, 49}。
这个新结果有什么用?它是否将 {9, 25, 49} 附加到现有的 {3, 5, 7},标记结果联合 R,然后从那里继续递归?或者它是否将 R 重新定义为这个新结果 {9, 25, 49} 并在以后进行所有联合?
两种选择都没有意义。 …
这是一个装配树,我想使用递归T-SQL查询(大概CTE)和下面的预期结果进行搜索。我想知道给定任何零件的每个组件的总量。
这意味着如果我搜索“铆钉”,我想知道程序集中每个级别的总数,而不仅仅是直接子项计数。
Assembly (id:1)
|
|-Rivet
|-Rivet
|-SubAssembly (id:2)
| |
| |-Rivet
| |-Bolt
| |-Bolt
| |-SubSubAssembly (id:3)
| |
| |-Rivet
| |-Rivet
|
|-SubAssembly (id:4)
|-Rivet
|-Bolt
DESIRED Results
-------
ID, Count
1 , 6
2 , 3
3 , 2
4 , 1
Run Code Online (Sandbox Code Playgroud)
目前,我可以获得直接父母,但想知道如何扩展我的 CTE 以允许我向上滚动此信息。
With DirectParents AS(
--initialization
Select InstanceID, ParentID
From Instances i
Where i.Part = 'Rivet'
UNION ALL
--recursive execution
Select i.InstanceID, i.ParentID
From PartInstances i INNER …Run Code Online (Sandbox Code Playgroud) 我需要从它的祖先计算后代的深度。当一个记录有 时object_id = parent_id = ancestor_id,它被认为是一个根节点(祖先)。我一直在尝试WITH RECURSIVE使用 PostgreSQL 9.4运行查询。
我不控制数据或列。数据和表架构来自外部源。该表正在不断增长。现在每天大约有 3 万条记录。树中的任何节点都可能丢失,并且它们将在某个时候从外部源中拉出。它们通常按created_at DESC顺序拉取,但数据是通过异步后台作业拉取的。
我们最初对这个问题有一个代码解决方案,但现在有 500 万行以上,几乎需要 30 分钟才能完成。
示例表定义和测试数据:
CREATE TABLE objects (
id serial NOT NULL PRIMARY KEY,
customer_id integer NOT NULL,
object_id integer NOT NULL,
parent_id integer,
ancestor_id integer,
generation integer NOT NULL DEFAULT 0
);
INSERT INTO objects(id, customer_id , object_id, parent_id, ancestor_id, generation)
VALUES (2, 1, 2, 1, 1, -1), --no parent yet
(3, 2, …Run Code Online (Sandbox Code Playgroud) 假设您有这样的nodes表:
CREATE TABLE nodes
(
node serial PRIMARY KEY,
parent integer NULL REFERENCES nodes(node),
ts timestamp NOT NULL DEFAULT now()
);
Run Code Online (Sandbox Code Playgroud)
它代表了一个标准的类似节点的树结构,根节点在顶部,几个子节点悬挂在根节点或其他子节点上。
让我们插入几个示例值:
INSERT INTO nodes (parent)
VALUES (NULL), (NULL), (NULL), (NULL), (1), (1), (1), (1), (6), (1)
, (6), (9), (6), (6), (3), (3), (3), (15);
Run Code Online (Sandbox Code Playgroud)
现在我想检索前 10 个根节点及其所有子节点,深度为 4:
WITH RECURSIVE node_rec AS
(
(SELECT 1 AS depth, * FROM nodes WHERE parent IS NULL LIMIT 10)
UNION ALL
SELECT depth + 1, n.*
FROM nodes …Run Code Online (Sandbox Code Playgroud) 如何更改系统范围的默认值MAXRECURSION?
默认情况下它是 100,但我需要将它增加到 1000 之类的东西。
我无法使用查询提示,因为我正在使用一个程序来获取我的查询并为我执行它,而且我无法绕过这个限制,不幸的是。
但是,我确实拥有服务器实例的管理员权限。我已经浏览了服务器方面,但我没有看到任何与查询选项或递归相关的内容。我认为必须有一个地方可以更新系统范围的默认值。
有任何想法吗?
我有这个有效的 CTE 示例。
我可以选择所有祖父母和所有孩子。
但是如何在一个语句中选择所有祖父母和所有孩子?
在这个例子中,如果我给“父亲”作为输入,我想要祖父,父亲,儿子作为输出。
我使用 PostgreSQL。但我认为这个问题应该是标准的SQL。
如果我使用 PostgreSQL 特定的语法,请纠正我。
DROP table if exists tree;
CREATE TABLE tree (
id SERIAL PRIMARY KEY,
name character varying(64) NOT NULL,
parent_id integer REFERENCES tree NULL
);
insert into tree values (1, 'Grandfather', NULL);
insert into tree values (2, 'Father', 1);
insert into tree values (3, 'Son', 2);
-- -------------------------------------
-- Getting all children works
WITH RECURSIVE rec (id) as
(
SELECT tree.id, tree.name from tree where name='Father'
UNION ALL
SELECT tree.id, …Run Code Online (Sandbox Code Playgroud) 我们有一个 SQL Server 数据库,它有一个数据库审计规范,它审计对数据库的所有执行操作。
CREATE DATABASE AUDIT SPECIFICATION [dbAudit]
FOR SERVER AUDIT [servAudit]
ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])
Run Code Online (Sandbox Code Playgroud)
我们发现,某些查询会将结果集中的每一行的标量函数的使用写入审计日志。当这种情况发生时,日志在我们可以 ETL 到它的最终休息位置之前就被填满了,我们的日志记录出现了空白。
不幸的是,由于合规性原因,我们不能简单地停止审核每条EXECUTE语句。
我们解决这个问题的第一个想法是使用Server AuditWHERE上的子句来过滤掉活动。代码如下所示:
WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )
Run Code Online (Sandbox Code Playgroud)
不幸的是,SQL Server 不允许关系 IN 运算符(可能是因为它不想在每次必须写入审核日志时进行查询)。
我们想避免编写一个存储过程,其硬代码object_id中WHERE条款,但是这是我们在解决这个问题的最好办法目前的想法。是否有我们应该考虑的替代方法?
我们注意到,当在递归 CTE 中使用标量函数时,它会导致查询为结果集中的每一行写入审计日志。
有一些标量值函数由供应商提供,我们无法删除或移动到备用数据库。
我正在创建一个概念图 [是的,我知道我已经包含了属性和键 - 但这只是让我在学习的同时巩固我正在做的事情] - 所以请把它当作概念性的,重点是关系和表格而不是如何绘制图表;)
我的障碍是: 我正在尝试确定对配置文件、位置和组织关系进行建模的最佳方式。
首先,规则:

Friend and Member differ, in that, Friends are like read-only and Members [depending on level] have full access to amend things.
更复杂的是,位置有自己的一套“进一步”细化规则,例如一个组织拥有两个位置,但根据位置规则,该组织的成员 [ …
recursive ×10
sql-server ×7
cte ×6
postgresql ×3
audit ×1
erd ×1
except ×1
functions ×1
inheritance ×1
order-by ×1
t-sql ×1
update ×1