Gibt es eine Möglichkeit, mit dieser Auswahl dieselben Ergebnisse mit einer einzigen Suche abzurufen?

8

Ist es möglich, mit einer einzigen Suche oder einem einzigen Scan dieselben Daten wie die folgenden abzurufen, indem entweder die Abfrage geändert oder die Strategie des Optimierers beeinflusst wird?

Code und ähnliches Schema befinden sich derzeit in SQL Server 2014.

Geben Sie hier die Bildbeschreibung ein

Repro-Skript. Installieren:

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

Abfrage:

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;

Niederreissen:

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

Ich denke, das ist wahrscheinlich nicht ideal modelliert. Ich versuche, vom Entwickler mehr Informationen darüber zu erhalten, wie das Schema ausgewählt wurde, bin aber neugierig, ob es einen TSQL-Trick gibt, den ich übersehen habe, da es einfacher ist, die Abfrage zu ändern als das Schema.

James L.
quelle

Antworten:

6

Ich würde es versuchen, aber ich habe keine Ahnung, ob es effizienter sein wird. Sie müssen DISTINCTDuplikate entfernen, damit dies UNION ALLmöglicherweise besser geeignet ist und keine zwei unterschiedlichen Vorgänge erforderlich sind:

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

UNION ALL Plan

UNION planen:

UNION-Plan

ypercubeᵀᴹ
quelle
3

Verwenden Sie cross apply, um Spalten in Zeilen zu entfernen

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
Serg
quelle
1
Nein, ich dachte das gleiche, aber das würde nicht funktionieren. Nicht einmal mit, UNIONda es Duplikate gibt, die entfernt werden müssen.
Ypercubeᵀᴹ
Du meinst, Sortierung ist unvermeidlich?
Serg
1
Ich meine, das DISTINCTist erforderlich. Siehe James 'Daten. Es gibt eine Reihe mit A,B,C,-,-,-und eine andere mit -,-,-,A,B,C. Die resultierenden Zeilen, eine aus A-Daten und die andere aus B-Daten, sind identisch und müssen entfernt werden. Selbst wenn das durch ersetzt UNION ALLwird UNION, kann dies nicht vermieden werden. (und mit "diesem" meine ich nicht "sortieren", sondern die "eindeutige" Operation.
Dies