今天,在使用sql server进行10年开发的第一次中,我在生产查询中使用了交叉连接。我需要将结果集填充到报表中,并发现具有creative where子句的两个表之间的交叉连接是一个很好的解决方案。我想知道在交叉连接的生产代码中有什么用处?
更新:Tony Andrews发布的代码非常接近我使用交叉联接的代码。相信我,我理解使用交叉连接的含义,并不会轻易做到这一点。我很高兴最终使用它(我是一个书呆子) - 有点像我第一次使用完全外连接的时候。
感谢大家的回答!这是我使用交叉连接的方式:
SELECT CLASS, [Trans-Date] as Trans_Date,
SUM(CASE TRANS
WHEN 'SCR' THEN [Std-Labor-Value]
WHEN 'S+' THEN [Std-Labor-Value]
WHEN 'S-' THEN [Std-Labor-Value]
WHEN 'SAL' THEN [Std-Labor-Value]
WHEN 'OUT' THEN [Std-Labor-Value]
ELSE 0
END) AS [LABOR SCRAP],
SUM(CASE TRANS
WHEN 'SCR' THEN [Std-Material-Value]
WHEN 'S+' THEN [Std-Material-Value]
WHEN 'S-' THEN [Std-Material-Value]
WHEN 'SAL' THEN [Std-Material-Value]
ELSE 0
END) AS [MATERIAL SCRAP],
SUM(CASE TRANS WHEN 'RWK' THEN [Act-Labor-Value] ELSE 0 END) AS [LABOR REWORK],
SUM(CASE TRANS
WHEN 'PRD' THEN [Act-Labor-Value]
WHEN 'TRN' THEN [Act-Labor-Value]
WHEN 'RWK' THEN [Act-Labor-Value]
ELSE 0
END) AS [ACTUAL LABOR],
SUM(CASE TRANS
WHEN 'PRD' THEN [Std-Labor-Value]
WHEN 'TRN' THEN [Std-Labor-Value]
ELSE 0
END) AS [STANDARD LABOR],
SUM(CASE TRANS
WHEN 'PRD' THEN [Act-Labor-Value] - [Std-Labor-Value]
WHEN 'TRN' THEN [Act-Labor-Value] - [Std-Labor-Value]
--WHEN 'RWK' THEN [Act-Labor-Value]
ELSE 0 END) -- - SUM([Std-Labor-Value]) -- - SUM(CASE TRANS WHEN 'RWK' THEN [Act-Labor-Value] ELSE 0 END)
AS [LABOR VARIANCE]
FROM v_Labor_Dist_Detail
where [Trans-Date] between @startdate and @enddate
--and CLASS = (CASE @class WHEN '~ALL' THEN CLASS ELSE @class END)
GROUP BY [Trans-Date], CLASS
UNION --REL 2/6/09 Pad result set with any missing dates for each class.
select distinct [Description] as class, cast([Date] as datetime) as [Trans-Date], 0,0,0,0,0,0
FROM Calendar_To_Fiscal cross join PRMS.Product_Class
where cast([Date] as datetime) between @startdate and @enddate and
not exists (select class FROM v_Labor_Dist_Detail vl where [Trans-Date] between @startdate and @enddate
and vl.[Trans-Date] = cast(Calendar_To_Fiscal.[Date] as datetime)
and vl.class= PRMS.Product_Class.[Description]
GROUP BY [Trans-Date], CLASS)
order by [Trans-Date], CLASS
答案 0 :(得分:36)
交叉联接的典型合法用途是显示例如交叉联接的报告。按产品和地区划分的总销售额如果没有在区域R中销售产品P,那么我们希望看到一行为零,而不是仅显示一行。
select r.region_name, p.product_name, sum(s.sales_amount)
from regions r
cross join products p
left outer join sales s on s.region_id = r.region_id
and s.product_id = p.product_id
group by r.region_name, p.product_name
order by r.region_name, p.product_name;
答案 1 :(得分:11)
我经常遇到的一个用途是将记录分成几个记录,主要用于报告目的。
想象一个字符串,其中每个字符代表相应小时内的某个事件。
ID | Hourly Event Data
1 | -----X-------X-------X--
2 | ---X-----X------X-------
3 | -----X---X--X-----------
4 | ----------------X--X-X--
5 | ---X--------X-------X---
6 | -------X-------X-----X--
现在您需要一份报告,显示当天发生的事件数量。用一张ID为1到24的表格交叉加入表格,然后运用你的魔法...
SELECT
[hour].id,
SUM(CASE WHEN SUBSTRING([data].string, [hour].id, 1) = 'X' THEN 1 ELSE 0 END)
FROM
[data]
CROSS JOIN
[hours]
GROUP BY
[hours].id
=>
1, 0
2, 0
3, 0
4, 2
5, 0
6, 2
7, 0
8, 1
9, 0
10, 2
11, 0
12, 0
13, 2
14, 1
15, 0
16, 1
17, 2
18, 0
19, 0
20, 1
21, 1
22, 3
23, 0
24, 0
答案 2 :(得分:2)
我有不同的报告预先过滤记录集(通过公司内部的各种业务线),但有计算需要公司范围内的收入百分比。记录源必须包含公司总数,而不是依赖于计算报告本身的总和。
示例:记录集包含每个客户的余额以及客户收入来自的业务线。该报告可能只显示“零售”客户。无法获得整个公司的余额总和,但报告显示了公司收入的百分比。
由于存在不同的余额字段,我觉得完全加入具有多个余额的视图(我也可以重复使用此公司总计视图)而不是多个字段组成子查询的情况并不复杂。
另一个是更新语句,其中需要创建多个记录(预设工作流程中每个步骤的一个记录)。
答案 3 :(得分:1)
这是一个CROSS JOIN替代INNER JOIN的地方。当两个要连接的表之间没有相同的值时,这是有用且合法的。例如,假设您有一个包含某个语句或公司文档的版本1,版本2和版本3的表,所有这些都保存在SQL Server表中,以便您可以动态地重新创建与订单关联的文档,在订单之后很久,并且在您的文档被重写为新版本之后很久。但是,您需要加入的两个表中只有一个(Documents表)具有VersionID列。这是一种方法:
SELECT DocumentText, VersionID =
(
SELECT d.VersionID
FROM Documents d
CROSS JOIN Orders o
WHERE o.DateOrdered BETWEEN d.EffectiveStart AND d.EffectiveEnd
)
FROM Documents
答案 4 :(得分:0)
我最近在用于销售预测的报告中使用了CROSS JOIN,报告需要打破销售人员在每个总帐帐户中所做的销售额。
所以在报告中我做了一些事情:
SELECT gla.AccountN, s.SalespersonN
FROM
GLAccounts gla
CROSS JOIN Salesperson s
WHERE (gla.SalesAnalysis = 1 OR gla.AccountN = 47500)
这为每个销售人员提供了每个GL帐户:
SalesPsn AccountN 1000 40100 1000 40200 1000 40300 1000 48150 1000 49980 1000 49990 1005 40100 1005 40200 1005 40300 1054 48150 1054 49980 1054 49990 1078 40100 1078 40200 1078 40300 1078 48150 1078 49980 1078 49990 1081 40100 1081 40200 1081 40300 1081 48150 1081 49980 1081 49990 1188 40100 1188 40200 1188 40300 1188 48150 1188 49980 1188 49990
答案 5 :(得分:0)
对于图表(报告),每个分组必须有一个记录,即使它是零。 (例如RadCharts)
答案 6 :(得分:0)
我从源数据中得到了破产现场的组合。 有5种不同的类型,但数据具有其中2种的组合。所以我创建了5个不同值的查找表,然后使用交叉连接为insert语句填写其余值。像这样
insert into LK_Insolvency (code,value)
select a.code+b.code, a.value+' '+b.value
from LK_Insolvency a
cross join LK_Insolvency b
where a.code <> b.code <--this makes sure the x product of the value with itself is not used as this does not appear in the source data.
答案 7 :(得分:-3)
我个人试图在我的查询中避免使用笛卡尔积。我想有一个结果集,你的联接的每个组合都可能有用,但通常如果我最终得到一个,我知道我有什么不对。