2009-02-07 10 views
10

Hôm nay, lần đầu tiên trong 10 năm phát triển với máy chủ sql, tôi đã sử dụng phép nối chéo trong truy vấn sản xuất. Tôi cần phải đệm một tập hợp kết quả vào một báo cáo và thấy rằng một kết hợp chéo giữa hai bảng với một quảng cáo trong đó mệnh đề là một giải pháp tốt. Tôi đã tự hỏi những gì sử dụng có bất cứ ai tìm thấy trong mã sản xuất cho việc tham gia chéo?sql cross join - sử dụng bất kỳ ai đã tìm thấy nó?

Cập nhật: mã được đăng bởi Tony Andrews rất gần với những gì tôi đã sử dụng tham gia chéo. Tin tôi đi, tôi hiểu những tác động của việc sử dụng một sự gia nhập chéo và sẽ không làm nhẹ đến thế. Tôi đã vui mừng khi cuối cùng đã sử dụng nó (tôi là một mọt sách) - giống như lần đầu tiên tôi sử dụng một sự tham gia đầy đủ bên ngoài.

Cảm ơn mọi người đã trả lời! Dưới đây là cách tôi sử dụng tham gia chéo:

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 

Trả lời

11

Một lần sử dụng tôi đã gặp rất nhiều là tách bản ghi ra nhiều bản ghi, chủ yếu cho mục đích báo cáo.

Hãy tưởng tượng một chuỗi nơi mỗi ký tự đại diện cho một số sự kiện trong giờ tương ứng.

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-- 

Bây giờ bạn muốn có báo cáo cho biết có bao nhiêu sự kiện xảy ra vào ngày nào. Chéo tham gia bảng với một bảng của các ID 1-24, sau đó làm việc kỳ diệu của bạn ...

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 
+0

trong trường hợp này không phải là dữ liệu của bạn thậm chí không ở dạng bình thường đầu tiên? Tất cả 24 giờ trong ngày được lưu trữ trong một trường. Đó không phải là vấn đề thực sự sao? – kralco626

+1

@ kralco626 - Chỉ vì bình thường hóa có lợi cho cơ sở dữ liệu quan hệ, điều đó không có nghĩa là dữ liệu nguồn của bạn được cấu trúc theo cách đó. SAS, ví dụ, thường sẽ mang lại các bộ dữ liệu đảm bảo xoay vòng theo cách này, hoặc các bộ điều khiển vi mô cung cấp các chuỗi theo dõi trạng thái, vv .. Điều này có thể tạo thành một phần của ETL của bạn. – MatBailie

-3

Cá nhân tôi cố gắng tránh các sản phẩm của Descartes trong các truy vấn của tôi. Tôi cho rằng có một tập hợp kết quả của tất cả các kết hợp tham gia của bạn có thể hữu ích, nhưng thường là nếu tôi kết thúc với một, tôi biết tôi có điều gì đó sai trái.

+0

Không chắc chắn câu trả lời này có liên quan: có lẽ bạn chỉ tránh tham gia chéo khi không thích hợp, chứ không phải khi chúng phù hợp? –

+3

@Tony: yes - bạn tránh tham gia chéo khi chúng không phù hợp và chúng không phù hợp thường xuyên hơn chúng phù hợp. Tuy nhiên, khi thích hợp, chúng là cách tốt nhất để giải quyết một số vấn đề. Đường viền câu trả lời không liên quan. –

+0

+0 tôi cũng vậy, đó là lý do tại sao tôi hỏi câu hỏi ... ;-) –

2

Tôi có các báo cáo khác nhau để lọc sơ lược các bản ghi (theo nhiều ngành nghề khác nhau trong công ty), nhưng có các tính toán yêu cầu tỷ lệ phần trăm doanh thu trên toàn doanh nghiệp. Nguồn thu phải chứa tổng số doanh nghiệp thay vì dựa vào việc tính toán tổng số tiền trong báo cáo.

Ví dụ: Bản ghi có số dư cho từng khách hàng và Doanh thu của Doanh nghiệp mà doanh thu của khách hàng đến. Báo cáo chỉ có thể hiển thị các khách hàng 'bán lẻ'. Không có cách nào để có được một khoản tiền cho toàn bộ công ty, nhưng báo cáo cho thấy tỷ lệ doanh thu của công ty.

Vì có các trường số dư khác nhau, tôi cảm thấy ít phức tạp hơn khi tham gia vào chế độ xem có nhiều số dư (tôi cũng có thể sử dụng lại tổng số công ty này) thay vì nhiều trường tạo truy vấn phụ.

Một số khác là một câu lệnh cập nhật trong đó nhiều bản ghi cần được tạo (một bản ghi cho mỗi bước trong quy trình quy trình làm việc được đặt trước).

36

Cách sử dụng hợp pháp điển hình của kết hợp chéo sẽ là báo cáo hiển thị ví dụ: tổng doanh thu theo sản phẩm và khu vực. Nếu không có doanh thu nào được tạo ra từ sản phẩm P trong vùng R thì chúng ta muốn thấy một hàng có số không, thay vì không hiển thị một hàng.

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; 
+5

Một số hình ảnh của dữ liệu hoặc kết quả thực sự sẽ giúp ích ở đây. – gideon

0

Tôi đã sử dụng một CROSS JOIN thời gian gần đây trong một báo cáo rằng chúng tôi sử dụng để bán forcasting, báo cáo cần phải phá vỡ số tiền bán hàng mà một nhân viên bán hàng đã thực hiện trong mỗi tài khoản General Ledger.

Vì vậy, trong báo cáo tôi làm gì đó để hiệu ứng này:

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

này mang lại cho tôi mỗi tài khoản GL cho mỗi người bán hàng như:

 
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 
+0

Thật khó để nói từ mẫu của bạn, nhưng có vẻ như bạn có thể vừa mới sử dụng JOIN bình thường và nhận được kết quả tương tự. –

+0

Phép nối chéo với mệnh đề "where" giống hệt với việc sử dụng phép nối bên trong (xem tại đây - http://msdn.microsoft.com/en-us/library/ms190690.aspx) – Flipster

0

Đối với biểu đồ (báo cáo), nơi mỗi phải nhóm có một kỷ lục ngay cả khi nó bằng không. (ví dụ: RadCharts)

1

Đây là một nơi mà CROSS JOIN thay thế cho INNER JOIN. Điều này hữu ích và hợp pháp khi không có giá trị giống hệt nhau giữa hai bảng để tham gia. Ví dụ: giả sử bạn có bảng chứa phiên bản 1, phiên bản 2 và phiên bản 3 của một số câu lệnh hoặc tài liệu công ty, tất cả được lưu trong bảng SQL Server để bạn có thể tạo lại tài liệu được liên kết với đơn đặt hàng, lâu sau khi đặt hàng, và lâu sau khi tài liệu của bạn được viết lại thành một phiên bản mới. Nhưng chỉ một trong hai bảng bạn cần tham gia (bảng Documents) có một cột VersionID. Dưới đây là một cách để thực hiện việc này:

SELECT DocumentText, VersionID = 
    (
    SELECT d.VersionID        
    FROM Documents d 
    CROSS JOIN Orders o 
    WHERE o.DateOrdered BETWEEN d.EffectiveStart AND d.EffectiveEnd 
    ) 
FROM Documents 
0

Tôi đã kết hợp trường mất khả năng thanh toán từ dữ liệu nguồn của mình. Có 5 loại riêng biệt nhưng dữ liệu có kết hợp 2 trong số này. Vì vậy, tôi tạo bảng tra cứu của 5 giá trị riêng biệt sau đó sử dụng một tham gia chéo cho một câu lệnh chèn để điền phần còn lại. giống như vậy

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.