C'è un modo per fare in modo che questa selezione recuperi gli stessi risultati con una sola ricerca?


8

È possibile recuperare gli stessi dati come segue con una sola ricerca o scansione, modificando la query o influenzando la strategia dell'ottimizzatore?

Codice e schema simili a questo sono attualmente su SQL Server 2014.

inserisci qui la descrizione dell'immagine

Script di riproduzione. Impostare:

USE tempdb;
GO
IF OBJECT_ID('dbo.TestUpload', 'U') IS NOT NULL 
  DROP TABLE dbo.TestUpload; 


CREATE TABLE dbo.TestUpload(
    JobRunId bigint NOT NULL,
    ThingAName nvarchar(255) NOT NULL,
    ThingAType nvarchar(255) NOT NULL,
    ThingAGranularity nvarchar(255) NOT NULL,
    ThingBName nvarchar(255) NOT NULL,
    ThingBType nvarchar(255) NOT NULL,
    ThingBGranularity nvarchar(255) NOT NULL
);
CREATE CLUSTERED INDEX IX_JobRunId ON dbo.TestUpload (JobRunId);

GO

INSERT INTO dbo.TestUpload (JobRunId, ThingAName, ThingAType, ThingAGranularity, ThingBName, ThingBType, ThingBGranularity)
  VALUES (1, 'A', 'B', 'C', 'D', 'E', 'F');
GO 10

INSERT INTO dbo.TestUpload (JobRunId, ThingAName, ThingAType, ThingAGranularity, ThingBName, ThingBType, ThingBGranularity)
  VALUES (1, 'D', 'E', 'F', 'A', 'B', 'C');
GO 10

Query:

DECLARE @JobRunID bigint = 1;

SELECT JobRunId,
  ThingAName AS Name, 
  ThingAType AS [Type], 
  ThingAGranularity AS Granularity
FROM dbo.TestUpload
WHERE JobRunId = @JobRunID
UNION
SELECT JobRunId,
  ThingBName AS Name, 
  ThingBType AS [Type], 
  ThingBGranularity AS Granularity
FROM dbo.TestUpload
WHERE JobRunId = @JobRunID;

Demolire:

IF OBJECT_ID('dbo.TestUpload', 'U') IS NOT NULL 
  DROP TABLE dbo.TestUpload;

Penso che questo probabilmente non sia modellato idealmente. Sto cercando di ottenere maggiori informazioni dallo sviluppatore su come è stato scelto lo schema, ma sono curioso di sapere se c'è un trucco TSQL che sto trascurando in quanto sarà più semplice modificare la query rispetto allo schema.

Risposte:


6

Ci proverei ma non ho idea se sarà più efficiente. È necessario DISTINCTrimuovere i duplicati, quindi UNION ALLpotrebbe essere più appropriato, non sono necessarie due operazioni distinte:

SELECT DISTINCT 
    JobRunId = @JobRunID, 
    d.*
FROM dbo.TestUpload
  CROSS APPLY 
    (   SELECT 
          ThingAName AS Name, 
          ThingAType AS [Type], 
          ThingAGranularity AS Granularity
      UNION                            -- or UNION ALL
        SELECT 
          ThingBName, 
          ThingBType, 
          ThingBGranularity
    ) AS d 
WHERE JobRunId = @JobRunID ;

UNION ALL Piano:

UNION ALL piano

UNION Piano:

Piano UNION


3

Usa la croce applicata per annullare la rotazione delle colonne in righe

SELECT --DISTINCT most probably
  JobRunId,
  ut.Name, 
  ut.[Type], 
  ut.Granularity
FROM dbo.TestUpload
CROSS APPLY (
  SELECT ThingBName AS Name, 
  ThingBType AS [Type], 
  ThingBGranularity AS Granularity
  UNION ALL 
  SELECT ThingAName AS Name, 
  ThingAType AS [Type], 
  ThingAGranularity AS Granularity
  ) ut
WHERE JobRunId = @JobRunID

1
No, ho pensato lo stesso ma non avrebbe funzionato. Nemmeno con UNIONpoiché ci sono duplicati che devono essere rimossi.
ypercubeᵀᴹ

Vuoi dire che l'ordinamento è inevitabile?
Serg

1
Voglio dire che DISTINCTè richiesto. Vedi i dati di James. C'è una riga con A,B,C,-,-,-e un'altra con -,-,-,A,B,C. Le righe risultanti una dai dati A e l'altra dai dati B sono identiche e devono essere rimosse. Anche se UNION ALLviene sostituito con UNION, questo non può essere evitato. (e con "questo" non intendo "ordinamento", intendo l'operazione "distinta". Potrebbe essere eseguita con ordinamento o hash, qualunque sia il metodo che l'ottimizzatore può e sceglie.)
ypercubeᵀᴹ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.