我有一个视图,它包含多个子查询,用于派生选择列表中的列(为了保持简单,我没有指定所有子查询)。我的问题是,用这么多子查询编写这样一个查询是完全可以的,还是有更好的方法来重写它以避免它们......任何可以遵循的最佳实践。我试着看一下派生查询或cte的选项,但由于某种原因我无法将这一块放在一起。我想尽可能消除那些重复的子查询。
SELECT a.id,
(
SELECT TOP 1
name
FROM x.dbo.Info l
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND stamp =
(
SELECT MIN(stamp)
FROM x.dbo.Info
WHERE orderno = l.orderno
AND releaseno = l.releaseno
AND status = 'Released'
)
ORDER BY stamp DESC
) [shop_name],
c.line_no,
a.status,
d.family,
(
SELECT TOP 1
name
FROM x.dbo.Info
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND status NOT LIKE 'backflus%'
AND status NOT LIKE 'so%'
ORDER BY stamp DESC
) AS [lastworkplace],
(
SELECT TOP 1
lstatus
FROM x.dbo.Info
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND status NOT LIKE 'backflus%'
AND status NOT LIKE 'so%'
ORDER BY stamp DESC
) AS [laststatus]
FROM BI.dbo.tblz a -- this is a view (not sure if that matters)
LEFT JOIN X.dbo.tblx b
ON b.id = a.salesorder
LEFT JOIN X.dbo.tbls c
ON c.tranid = a.salesorder
AND c.itemid = a.assemblyid
AND c.serialnum = a.ordercode
LEFT JOIN Z.dbo.tbli d
ON d.prodline = LEFT(COALESCE(STUFF(a.assemblyid, CHARINDEX('+', a.assemblyid), 1, ''), a.assemblyid), 2)
WHERE a.id = 'p'
AND
(
LEFT(a.prun, 8) >= '20120101'
OR a.prun IS NULL
)
UNION ALL
SELECT a.id,
(
SELECT TOP 1
name
FROM x.dbo.Info l
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND stamp =
(
SELECT MIN(stamp)
FROM x.dbo.Info
WHERE orderno = l.orderno
AND releaseno = l.releaseno
AND status = 'Released'
)
ORDER BY stamp DESC
) [shop_name],
c.line_no,
a.status,
d.family,
(
SELECT TOP 1
name
FROM x.dbo.Info
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND status NOT LIKE 'backflus%'
AND status NOT LIKE 'so%'
ORDER BY stamp DESC
) AS [lastworkplace],
(
SELECT TOP 1
lstatus
FROM x.dbo.Info
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND status NOT LIKE 'backflus%'
AND status NOT LIKE 'so%'
ORDER BY stamp DESC
) AS [laststatus]
FROM BI.dbo.tblz a -- this is a view (not sure if that matters)
LEFT JOIN X.dbo.tblx b
ON b.id = a.salesorder
LEFT JOIN X.dbo.tbls c
ON c.tranid = a.salesorder
AND c.itemid = a.assemblyid
AND c.serialnum = a.ordercode
LEFT JOIN Z.dbo.tbli d
ON d.prodline = LEFT(COALESCE(STUFF(a.assemblyid, CHARINDEX('+', a.assemblyid), 1, ''), a.assemblyid), 2)
WHERE a.id = 'm'
AND
(
LEFT(a.prun, 8) >= '20120101'
OR a.prun IS NULL
);
答案 0 :(得分:0)
您可以使用CTE重写您的选择。它更具可读性。引用文档:
指定临时命名结果集,称为公用表表达式(CTE)。这是从简单查询派生而来,并在单个SELECT,INSERT,UPDATE或DELETE语句的执行范围内定义。此子句也可以在CREATE VIEW语句中用作其定义SELECT语句的一部分。公用表表达式可以包含对自身的引用。这被称为递归公用表表达式。
只是一个简单的示例:
WITH
step1 as
( select a+1 as x, b-1 as y
from t
),
step2 as
( select x*2 as i, y/2 as j
from step1
)
select i+j as r
from step2;
你可以用这种方式链接几个句子。
答案 1 :(得分:0)
以下情况:
SELECT TOP 1
[some column]
FROM x.dbo.Info
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND status NOT LIKE 'backflus%'
AND status NOT LIKE 'so%'
ORDER BY stamp DESC
您可以尝试OUTER APPLY
查看this和this例如:
SELECT a.id,
(
SELECT TOP 1
name
FROM x.dbo.Info l
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND stamp =
(
SELECT MIN(stamp)
FROM x.dbo.Info
WHERE orderno = l.orderno
AND releaseno = l.releaseno
AND status = 'Released'
)
ORDER BY stamp DESC
) [shop_name],
c.line_no,
a.status,
d.family,
SomeInfo.name AS [lastworkplace], --<-- Note the change
SomeInfo.lstatus AS [laststatus] --<-- Note the change
FROM BI.dbo.tblz a -- this is a view (not sure if that matters)
LEFT JOIN X.dbo.tblx b
ON b.id = a.salesorder
LEFT JOIN X.dbo.tbls c
ON c.tranid = a.salesorder
AND c.itemid = a.assemblyid
AND c.serialnum = a.ordercode
LEFT JOIN Z.dbo.tbli d
ON d.prodline = LEFT(COALESCE(STUFF(a.assemblyid, CHARINDEX('+', a.assemblyid), 1, ''), a.assemblyid), 2)
OUTER APPLY( --<-- Note the extra join
SELECT TOP 1
*
FROM x.dbo.Info
WHERE orderno = a.orderno
AND releaseno = a.releaseno
AND status NOT LIKE 'backflus%'
AND status NOT LIKE 'so%'
ORDER BY stamp DESC
) AS SomeInfo
WHERE a.id = 'p'
AND
(
LEFT(a.prun, 8) >= '20120101'
OR a.prun IS NULL
)