我一直在CROSS / OUTER APPLY和同事一起看,我们正在努力寻找现实生活中使用它们的例子.
我花了很多时间看看我何时应该使用Cross Apply而不是Inner Join?和谷歌搜索但主要(唯一)的例子似乎很奇怪(使用表中的行数来确定从另一个表中选择多少行).
我认为这种情况可能会受益于OUTER APPLY:
联系人表(每个联系人包含1条记录)通讯条目表(每个联系人可以包含n个电话,传真,电子邮件)
但是使用子查询,公共表表达式,OUTER JOIN与RANK()和OUTER APPLY似乎都同样执行.我猜这意味着该方案不适用于APPLY.
请分享一些现实生活中的例子并帮助解释这个功能!
由于Postgres能够进行LATERAL连接,我一直在阅读它,因为我目前为我的团队执行复杂的数据转储,其中包含大量低效的子查询,这使得整个查询需要四分钟或更长时间.
我知道LATERAL联接可能能够帮助我,但即使在阅读了像Heap Analytics 这样的文章之后,我仍然没有完全遵循.
LATERAL加入的用例是什么?LATERAL连接和子查询之间有什么区别?
我有一个不带参数的存储过程,它返回两个字段.存储过程汇总应用于租户的所有事务,并返回租户的余额和ID.
我想使用它返回的记录集和查询,我需要在租户的id上加入它的结果.
这是我目前的查询:
SELECT t.TenantName, t.CarPlateNumber, t.CarColor, t.Sex, t.SSNO, t.Phone, t.Memo,
u.UnitNumber,
p.PropertyName
FROM tblTenant t
LEFT JOIN tblRentalUnit u
ON t.UnitID = u.ID
LEFT JOIN tblProperty p
ON u.PropertyID = p.ID
ORDER BY p.PropertyName, t.CarPlateNumber
Run Code Online (Sandbox Code Playgroud)
存储过程是这样的:
SELECT tenant.ID AS TenantID, SUM(ISNULL(trans.Amount,0)) AS TenantBalance FROM tblTenant tenant
LEFT JOIN tblTransaction trans
ON tenant.ID = trans.TenantID
GROUP BY tenant.ID
Run Code Online (Sandbox Code Playgroud)
我想从存储过程中添加余额.
我怎样才能做到这一点?
我有一个表值函数返回一个表.当我尝试JOIN使用另一个表的表值函数时,我没有得到任何结果,但是当我将函数的结果复制到一个实际的表并执行相同的连接时,我得到了预期的结果.
查询看起来像这样:
Select *
From myTable
INNER JOIN fn_function(@parm1, @param2)
ON ....
Run Code Online (Sandbox Code Playgroud)
总而言之,我有大约4个这样的查询,每个查询的功能略有不同,但所有函数都生成相同的表但数据不同.对于其中一些查询的INNER JOIN作品,但对于其他人则没有.
有人建议为什么会这样吗?
主表
x------x--------------------x
| Id | Name |
x------x--------------------x
| 1 | A |
| 2 | B |
| 3 | C |
x------x--------------------x
Run Code Online (Sandbox Code Playgroud)
详情表
x------x--------------------x-------x
| Id | PERIOD | QTY |
x------x--------------------x-------x
| 1 | 2014-01-13 | 10 |
| 1 | 2014-01-11 | 15 |
| 1 | 2014-01-12 | 20 |
| 2 | 2014-01-06 | 30 |
| 2 | 2014-01-08 | 40 |
x------x--------------------x-------x
Run Code Online (Sandbox Code Playgroud)
我LEFT JOIN和OUTER APPLY使用时得到相同的结果.
LEFT JOIN
SELECT …Run Code Online (Sandbox Code Playgroud) 我对CROSS APPLY参数化表值函数有问题.这是简化的伪代码示例:
SELECT *
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) AS lor
CROSS APPLY dbo.HeavyTableValuedFunction(lor.ID) AS htvf
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
WHERE ...
Run Code Online (Sandbox Code Playgroud)
LOT_OF_ROWS_TABLE返回许多行.LOT_OF_ROWS_TABLE并ANOTHER_TABLE只返回一行或几行.我的问题:
LOT_OF_ROWS_TABLE无论在加入时数据是否受限这一事实,都会为所有返回的行调用该函数ANOTHER_TABLE.
选择必须采用所示的格式 - 它是生成的,实际上它更加困难.
当我尝试重写它时,它可以非常快,但它不能像这样重写:
SELECT *
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) AS lor
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
CROSS APPLY dbo.HeavyTableValuedFunction(at.ID) AS htvf …Run Code Online (Sandbox Code Playgroud) 我有一个SQL表字段中包含的XML值列表,如下所示:
<valuelist xmlns="" name="VL_IncCompCondVL">
<li value="BL" item="BLOCKED" />
<li value="NK" item="NO KEY" />
<li value="FL" item="FLOODED" />
<li value="TD" item="TORN DOWN" />
<li value="UL" item="UNABLE TO LOCATE" />
</valuelist>
Run Code Online (Sandbox Code Playgroud)
我希望能够像这样创建一个临时SQL表:
CREATE TABLE #incompleteCode
(
value nvarchar(2),
item nvarchar(20)
)
Run Code Online (Sandbox Code Playgroud)
并使用XML中的所有值/项填充它,以便我可以使用临时表与另一个SELECT语句进行JOIN.
SELECT Data.value('(/valuelist/li/@item)[1]', 'nvarchar(50)') AS Item
FROM ValueList
WHERE Name = 'VL_IncCompCondVL'
Run Code Online (Sandbox Code Playgroud)
那个语句让我第一个,如果我将[1]增加到[2],依此类推,我可以逐个选择每个属性.但我必须相信有一种方法可以让他们全部.我尝试了一些变化,我只是没有搞清楚.我想我需要在某个地方使用*通配符.
查询1:占用最长时间的前10个代码
select top 10
source_code,
stats.total_elapsed_time/1000000 as seconds,
last_execution_time from sys.dm_exec_query_stats as stats
cross apply(SELECT
text as source_code
FROM sys.dm_exec_sql_text(sql_handle)) AS query_text
order by total_elapsed_time desc
Run Code Online (Sandbox Code Playgroud)
Query2:占用最大physical_reads的前10个代码
select top 10
source_code,
stats.total_elapsed_time/1000000 as seconds,
last_execution_time from sys.dm_exec_query_stats as stats
cross apply(SELECT
text as source_code
FROM sys.dm_exec_sql_text(sql_handle)) AS query_text
order by total_physical_reads desc
Run Code Online (Sandbox Code Playgroud)
取自本文
我在sql中有两个表.一个是测试用例表,另一个是测试运行表,其中一个外键链接回测试用例.我想为每个测试用例获得最近10次测试运行.如果我不需要,我不想循环,但我没有看到任何其他方法来解决这个问题.在sql server中处理这类事情最有效的方法是什么?
表结构是:
create table fruit (
id int identity(1,1),
name varchar(max)
)
create table fruit_allocation (
id int identity(1,1),
fruit_id int references fruit(id),
customer_id int references store(id),
amount float,
)
create table measurement (
fruit_allocation_id int references fruit_allocation(id),
measurement_date datetime,
measurement float,
)
Run Code Online (Sandbox Code Playgroud)
每个水果都可以分配给多个客户,创建一个fruit_allocation记录.每个fruit_allocation记录可以有多个度量.
我想为每个fruit_allocation选择最新的度量给出一个水果ID
到目前为止,我有以下内容:
select *
from measurement
where fruit_allocation_id in (select id
from fruit_allocation
where fruit_id = 10)
Run Code Online (Sandbox Code Playgroud)
这将返回该水果的所有测量值,我想每个fruit_allocation返回1个测量值.
sql-server ×8
sql ×6
t-sql ×2
cross-apply ×1
function ×1
iteration ×1
lateral-join ×1
left-join ×1
mysql ×1
outer-apply ×1
performance ×1
postgresql ×1
restriction ×1
sql-function ×1
subquery ×1
xml ×1
xpath ×1