我有大约3500个防洪设施,我想将其表示为确定流路径的网络(基本上是有向图).我目前正在使用SqlServer和CTE递归检查所有节点及其上游组件,只要上游路径不分叉,这就可以工作.然而,由于增加了上游复杂性,一些查询比其他查询指数长得多,即使它们在物理上不太远(即两个或三个"下游"段).在某些情况下,我会在杀死查询之前让它超过十分钟.我正在使用一个简单的双列表,一列是设施本身,另一列是第一列中列出的设施的上游设施.
我尝试使用当前工具添加索引以帮助加快速度,但这没有任何区别.并且,对于图中可能的连接,任何节点可以具有多个上游连接,并且可以从多个"下游"节点连接.
当然有可能在数据中有循环,但我还没有找到一种好的方法来验证这一点(除了CTE查询报告最大递归计数命中时;这些很容易修复).
所以,我的问题是,我存储这些信息是错误的吗?有没有比CTE更好的方法来查询上游点?
我有一些分层数据 - 每个条目都有一个id和一个(可空)父条目id.我想检索给定条目下树中的所有条目.这是在SQL Server 2005数据库中.我在C#3.5中使用LINQ to SQL查询它.
LINQ to SQL不直接支持公用表表达式.我的选择是使用几个LINQ查询在代码中汇编数据,或者在面向CTE的数据库上进行查看.
当数据量变大时,您认为哪个选项(或其他选项)会表现更好?Linq to SQL是否支持SQL Server 2008的HierarchyId类型?
让我们尝试一个更简单的例子,这样人们可以围绕这些概念,并有一个实际的例子,你可以复制并粘贴到SQL Query Analizer:
想象一个具有层次结构的节点表:
A
- B
- C
Run Code Online (Sandbox Code Playgroud)
我们可以在Query Analizer中开始测试:
CREATE TABLE ##Nodes
(
NodeID varchar(50) PRIMARY KEY NOT NULL,
ParentNodeID varchar(50) NULL
)
INSERT INTO ##Nodes (NodeID, ParentNodeID) VALUES ('A', null)
INSERT INTO ##Nodes (NodeID, ParentNodeID) VALUES ('B', 'A')
INSERT INTO ##Nodes (NodeID, ParentNodeID) VALUES ('C', 'B')
Run Code Online (Sandbox Code Playgroud)
期望的输出:
ParentNodeID NodeID GenerationsRemoved
============ ====== ==================
NULL A 1
NULL B 2
NULL C 3
A B 1
A C 2
B C 1
Run Code Online (Sandbox Code Playgroud)
现在建议的CTE表达式,输出不正确:
WITH NodeChildren …Run Code Online (Sandbox Code Playgroud) 我们写下一个CTE sql
WITH yourCTE AS
(
SELECT .... FROM :... WHERE.....
) SELECT * FROM yourCTE
Run Code Online (Sandbox Code Playgroud)
将sql放入块中会有什么好处.我认为,如果我们把复杂的sql放入块中,那么我们就可以编写像sql一样的了SELECT * FROM yourCTE.好像我正在访问视图.在性能方面使用CTE的附加优势是什么.请讨论.谢谢
我昨天回答了一个递归的CTE,它揭示了这些在SQL Server中实现的方式的问题(也可能在其他RDBMS中?).基本上,当我尝试使用ROW_NUMBER当前的递归级别时,它会针对当前递归级别的每个行子集运行.我希望这可以在真正的SET逻辑中工作,并针对整个当前的递归级别运行.
看来,从这篇MSDN文章中,我发现的问题是预期的功能:
CTE的递归部分中的分析和聚合函数应用于当前递归级别的集合,而不应用于CTE的集合.像ROW_NUMBER这样的函数只对当前递归级别传递给它们的数据子集起作用,而不是对整个CTE递归部分的数据集合起作用.有关更多信息,请参阅J.在递归CTE中使用分析函数.
在我的挖掘中,我找不到解释为什么选择这样做的方式呢?这在基于集合的语言中更像是一种过程方法,因此这对我的SQL思维过程起作用,在我看来非常混乱.是否有人知道和/或可以解释为什么递归CTE以递归方式处理递归级别的分析函数?
以下是帮助可视化的代码:
请注意,RowNumber每个代码输出中的列.
WITH myCTE
AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY Score desc) AS RowNumber, 1 AS RecurseLevel
FROM tblGroups
WHERE ParentId IS NULL
UNION ALL
SELECT tblGroups.*,
ROW_NUMBER() OVER (ORDER BY myCTE.RowNumber , tblGroups.Score desc) AS RowNumber,
RecurseLevel + 1 AS RecurseLevel
FROM tblGroups
JOIN myCTE
ON myCTE.GroupID = tblGroups.ParentID
)
SELECT *
FROM myCTE
WHERE RecurseLevel = 2; …Run Code Online (Sandbox Code Playgroud) sql sql-server row-number common-table-expression recursive-cte
我有这个让我头疼的问题......
说,我有一个包含数千行的表,表的结构包含父 - >子关系.
这种关系可以达到6个级别.这是表结构的示例:
ProductId | ParentId | Levels
1174 0 1174
311 1174 311, 1174
1186 311 1186, 311, 1174
448 1186 448, 1186, 311, 1174
3365 448 3365, 448, 1186, 311, 1174
Run Code Online (Sandbox Code Playgroud)
我们有一个循环遍历整个表以获取关系并保存"级别"列的进程,这个过程非常慢(因为循环)并且我尝试了一些cte来获得关系,但是很难实现.
到目前为止,我已经尝试过这个cte,但它没有做我希望的事情,而且,它似乎在复制行...
;With Parents(ProductId, ParentId, Levels)
As(
Select ProductId, ParentId, Levels
From Products
Where ParentId = 0
Union All
Select p.ProductId, p.ParentId, p.Levels
From Products p
Join Parents cte On cte.ProductId = p.ParentId
)
Select *
From Parents
Run Code Online (Sandbox Code Playgroud)
正如我之前提到的,我们有一个循环表的过程,它完成它的工作,但它可能需要长达30分钟,我的问题是有更好的方法来做到这一点?我知道CTE允许我这样做,但我很糟糕,同样,应该在桌面上计算和更新关卡列,是否可能?
这是一个Sqlfiddle以防有人可以提供帮助,谢谢!
有没有办法为硬编码值列表构建CTE?例如,我有一个已知ID的列表(即101,102,105,200 ...),我如何能够创建一个名为ID的列的CTE,但所有ID值在查询中都是硬编码的?顺便说一句,我需要在Oracle中运行此查询.谢谢!
我在这里的问题是,是什么区别CTE和View在SQL.我的意思是在哪种情况下我应该使用CTE和哪种情况View.我知道两者都是某种虚拟表,但我不能区分它们的用途.
更新1:
例如:我有一个填充了trades(tbl_trade)的数据库.我需要从3.5百万条记录中选择当前时间到当前时间打开的交易然后操纵数据(在虚拟表上使用不同的查询 - 这看起来像View).这里的问题是我想要一个SUM3-4列,然后我需要SUM一些列并创建一个带有结果的虚拟列(看起来像CTE).
例如:tbl_trade有列:profit,bonus和expenses.我需要的SUM(profit),SUM(bonus),SUM(expenses)和新的一列total,这将是等于SUM(profit)+ SUM(bonus)+ SUM(expenses).
PS.重新运行查询SUM不是一个选项,因为我已经有了结果.
提前致谢!
我有一个复杂的SQL查询,可以简化到下面:
Select ColA,ColB,ColC,ColD
From MyTable
Where (ColA In (Select ItemID From Items Where ItemName like '%xxx%')
or ColB In (Select ItemID From Items Where ItemName like '%xxx%'))
Run Code Online (Sandbox Code Playgroud)
如您所见,子查询出现两次.编译器是否足够智能来检测它并仅获取子查询的结果一次?或者子查询运行两次?
仅供参考,表项目大约有20,000行,MyTable有大约200,000行.
是否有另一种方法来重写此SQL语句,以便子查询只出现/运行一次?
更新:主查询中的Where子句是动态的,仅在需要时添加(即仅在用户搜索"xxx"时).因此,不可能对主select语句进行更改或重新构造查询.
我是SO和postgres的新手所以请原谅我的无知.尝试使用类似于本文中的解决方案在postgres中获取图表的集群在PostgreSQL中查找集群给定节点
唯一的区别是我的id是一个UUID,我使用varchar(255)来存储这个id
当我尝试运行查询时,我收到以下错误(但不知道如何投射):
ERROR: recursive query "search_graph" column 1 has type character varying(255)[] in non-recursive term but type character varying[] overall
Run Code Online (Sandbox Code Playgroud)
SQL状态:42804提示:将非递归项的输出强制转换为正确的类型.性格:81
我的代码(与上一篇文章基本相同):
WITH RECURSIVE search_graph(path, last_profile1, last_profile2) AS (
SELECT ARRAY[id], id, id
FROM node WHERE id = '408d6b12-d03e-42c2-a2a7-066b3c060a0b'
UNION ALL
SELECT sg.path || m.toid || m.fromid, m.fromid, m.toid
FROM search_graph sg
JOIN rel m
ON (m.fromid = sg.last_profile2 AND NOT sg.path @> ARRAY[m.toid])
OR (m.toid = sg.last_profile1 AND NOT sg.path @> ARRAY[m.fromid])
)
SELECT DISTINCT unnest(path) FROM …Run Code Online (Sandbox Code Playgroud) sql ×6
sql-server ×6
t-sql ×2
c#-3.0 ×1
dynamic-sql ×1
graph-theory ×1
linq ×1
oracle ×1
postgresql ×1
rdbms ×1
row-number ×1
sql-view ×1