11

今天,在使用 sql server 开发 10 年来,我第一次在生产查询中使用了交叉联接。我需要将结果集填充到报告中,并发现使用创造性 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
4

8 回答 8

37

交叉连接的典型合法用途是显示例如按产品和地区的总销售额的报告。如果区域 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;
于 2009-02-07T11:03:32.203 回答
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
于 2009-02-09T22:44:37.953 回答
2

我有不同的报告预先过滤记录集(按公司内的各种业务线),但有计算需要公司范围内的收入百分比。记录源必须包含公司总数,而不是依赖于计算报告本身中的总和。

示例:记录集包含每个客户的余额以及客户收入来源的业务线。该报告可能只显示“零售”客户。无法获得整个公司的余额总和,但报告显示了公司收入的百分比。

由于有不同的余额字段,我觉得完全联接具有多个余额的视图(我也可以重用该公司总计的视图)而不是多个字段组成子查询并不那么复杂。

另一种是更新语句,其中需要创建多条记录(预设工作流程中的每个步骤都有一条记录)。

于 2009-02-07T04:24:44.457 回答
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 
于 2013-08-20T19:52:09.063 回答
0

我最近在我们用于销售预测的报告中使用了 CROSS JOIN,该报告需要细分销售人员在每个总帐帐户中所做的销售量。

因此,在报告中,我为此做了一些事情:

SELECT gla.AccountN, s.SalespersonN
FROM
    GLAccounts gla
    CROSS JOIN Salesperson s
WHERE (gla.SalesAnalysis = 1 OR gla.AccountN = 47500)

这给了我每个销售人员的每个 GL 帐户,例如:

销售Psn 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
于 2009-03-28T02:06:17.270 回答
0

对于每个分组都必须有记录的图表(报告),即使它为零。(例如 RadCharts)

于 2011-12-20T14:31:48.593 回答
0

我从源数据中获得了 am insolvency 字段的组合。有 5 种不同的类型,但数据包含其中 2 种的组合。所以我创建了 5 个不同值的查找表,然后使用交叉连接插入语句来填写其余部分。像这样

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.
于 2014-11-11T16:36:58.930 回答
-3

我个人尽量避免在我的查询中使用笛卡尔积。我想你的加入的每个组合都有一个结果集可能很有​​用,但通常如果我最终得到一个,我知道我有问题。

于 2009-02-07T03:57:48.240 回答