Domanda

Oggi, per la prima volta in 10 anni di sviluppo con sql server ho usato un cross join in una query di produzione. Avevo bisogno di pad un set di risultati di una relazione e ha scoperto che un cross join tra due tabelle con un creativo in cui la clausola è stata una buona soluzione. Mi chiedevo che cosa serve qualcuno ha trovato nel codice di produzione per il cross join?

Aggiornamento: il codice pubblicato da Tony Andrews è molto vicino a quello che ho usato il cross join per. Mi creda, capisco le implicazioni dell'utilizzo di un cross join e non lo farei con tanta leggerezza. Ero entusiasta di avere finalmente usato (io sono un secchione) - un po 'come il tempo che ho prima usato un full outer join.

Grazie a tutti per le risposte! Ecco come ho usato i cross join:

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
È stato utile?

Soluzione

Un uso che ho incontrato un sacco è record spaccare fuori in diversi record, principalmente per scopi di segnalazione.

Immaginate una stringa in cui ogni carattere rappresenta un evento nel corrispondente ore.

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

Ora si vuole un rapporto che mostra come molti eventi accaduti in quale giorno. Croce si uniscono al tavolo con una tabella di ID da 1 a 24, poi lavorare la tua magia ...

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

Altri suggerimenti

Un tipico utilizzo legittimo di un cross join sarebbe un rapporto che mostra esempio vendite totali per prodotto e regione. Se nessuna vendita sono state fatte di prodotto P nella regione R poi vogliamo vedere una riga con uno zero, piuttosto che semplicemente non mostrando una fila.

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;

Ho diversi rapporti che Prefiltro il set di record (da varie linee di business all'interno della società), ma c'erano i calcoli che richiedevano percentuali di entrate ditta-larga. Il recordsource doveva contenere il totale fermo, invece di basarsi sul calcolo della somma complessiva nella relazione stessa.

Esempio: Il recordset ha saldi per ogni cliente e la Line of Business entrate del cliente proviene. La relazione può mostrare solo clienti al dettaglio. Non v'è alcun modo per ottenere una somma dei saldi per l'intera azienda, ma il rapporto mostra la percentuale delle entrate della società.

Dato che ci sono diversi campi di equilibrio, ho sentito che era meno complicato di avere piena unirsi con la vista che ha diversi saldi (posso anche riutilizzare questo punto di vista dei totali impresa) al posto del più campi costituiti da query sub.

Un altro è un'istruzione di aggiornamento dove più record dovevano essere creato (un record per ogni fase di un processo di workflow prestabilito).

Ecco uno, dove il CROSS JOIN sostituti per un INNER JOIN. Ciò è utile e legittimo quando non ci sono valori identici tra due tabelle su cui aderire. Ad esempio, si supponga di avere una tabella che contiene la versione 1, versione 2 e la versione 3 di qualche documento dichiarazione o la società, il tutto salvato in una tabella di SQL Server in modo che è possibile ricreare un documento che è associato con un ordine, al volo, molto tempo dopo l'ordine, e molto tempo dopo il documento è stato riscritto in una nuova versione. Ma solo uno dei due tavoli è necessario iscriversi (la tabella Documenti) ha una colonna VERSIONID. Ecco un modo per farlo:

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

Ho usato un CROSS JOIN di recente in un rapporto che usiamo per le vendite forcasting, il rapporto ha bisogno di uscire la quantità di vendite che una persona di vendita ha fatto in ogni conto di contabilità generale.

Quindi, nella relazione che faccio qualcosa di questo tenore:

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

Questo mi dà ogni account GL per ogni persona di vendite come:

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

Per la creazione di grafici (report) in cui ogni raggruppamento deve avere un record anche se è pari a zero. (Ad esempio RadCharts)

ho avuto combinazioni di campo insolvenza del mattino dai miei dati di origine. Ci sono 5 tipi distinti, ma i dati sono combinazioni di 2 di questi. Così ho creato tabella di ricerca dei 5 valori distinti poi utilizzato un cross join per un'istruzione INSERT per compilare il resto. in questo modo

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.

Io personalmente cerco di evitare cartesiano di prodotti nelle mie query. Suppongo che ho un set di risultati di ogni combinazione della vostra unirsi potrebbe essere utile, ma di solito se io alla fine con uno, so di avere qualcosa che non va.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top