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