Sql cross join - какое использование кому-либо удалось найти?

Сегодня, впервые за 10 лет разработки с SQL-сервером, я использовал кросс-соединение в производственном запросе. Мне нужно было поместить результирующий набор в отчет и обнаружить, что перекрестное соединение между двумя таблицами с предложением объявления where было хорошим решением. Мне было интересно, какое использование кто-либо нашел в производственном коде для перекрестного соединения?

Обновление: код, отправленный Тони Эндрюсом, очень близок к тому, к чему я использовал cross cross. Поверьте мне, я понимаю последствия использования перекрестного соединения и не делал бы этого легкомысленно. Я был в восторге от того, что наконец использовал его (я такой ботаник) - вроде как время, когда я впервые использовал полное внешнее соединение.

Спасибо всем за ответы! Вот как я использовал перекрестное соединение:

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

Ответ 1

Одно из применений, с которыми я столкнулся, - это разделение записей на несколько записей, главным образом для целей отчетности.

Представьте строку, в которой каждый символ представляет какое-либо событие в течение соответствующего часа.

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

Теперь вам нужен отчет, который показывает, сколько событий произошло в тот день. Перекреститесь со столом с таблицей с идентификаторами от 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

Типичным законным использованием перекрестного соединения будет отчет, который показывает, например, общий объем продаж по продуктам и регионам. Если в области 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;

Ответ 3

У меня есть разные отчеты, которые предфильтруют набор записей (по различным направлениям деятельности в фирме), но были расчеты, которые требовали процента от дохода по всей стране. Источник записи должен был содержать общую сумму, а не полагаться на вычисление общей суммы в самом отчете.

Пример. У набора записей есть балансы для каждого клиента и Линия бизнеса, из которых поступает доход клиента. В отчете могут отображаться только "розничные" клиенты. Невозможно получить сумму балансов для всей фирмы, но в отчете указывается процент от прибыли фирмы.

Поскольку есть разные поля баланса, я чувствовал, что было бы сложнее иметь полное соединение с представлением, имеющим несколько балансов (я также могу повторно использовать это представление итогов фирмы) вместо нескольких полей, составляющих подзапросы.

Другой - это оператор обновления, в котором необходимо создать несколько записей (одна запись для каждого шага в заданном процессе рабочего процесса).

Ответ 4

Здесь один, где 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 

Ответ 5

Недавно я использовал 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

Ответ 6

Для диаграмм (отчетов), где каждая группа должна иметь запись, даже если она равна нулю. (например, RadCharts)

Ответ 7

У меня были комбинации полей несостоятельности am из моих исходных данных. Существует 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.

Ответ 8

Я лично стараюсь избегать декартового продукта в моих запросах. Я предполагаю, что набор результатов из каждой комбинации вашего соединения может быть полезен, но обычно, если я в конечном итоге с ним, я знаю, что у меня что-то не так.