Apakah ada cara untuk membuat pilih ini mengambil hasil yang sama dengan pencarian tunggal?

8

Apakah mungkin untuk mengambil data yang sama dengan yang berikut dengan pencarian tunggal atau pemindaian, baik dengan memodifikasi kueri atau memengaruhi strategi pengoptimal?

Kode dan skema yang mirip dengan ini saat ini ada di SQL Server 2014.

masukkan deskripsi gambar di sini

Skrip repro. Mendirikan:

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

Pertanyaan:

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;

Robek:

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

Saya pikir ini mungkin tidak dimodelkan secara ideal. Saya mencoba untuk mendapatkan lebih banyak informasi dari pengembang tentang bagaimana skema dipilih tetapi saya ingin tahu apakah ada trik TSQL yang saya hadapi karena akan lebih mudah untuk mengubah kueri daripada skema.

James L.
sumber

Jawaban:

6

Saya akan mencoba ini tetapi saya tidak tahu apakah itu akan lebih efisien. Anda perlu DISTINCTmenghapus duplikat, jadi UNION ALLmungkin lebih tepat, tidak perlu untuk dua operasi yang berbeda:

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

SEMUA rencana UNION

UNION rencana:

Rencana UNION

ypercubeᵀᴹ
sumber
3

Gunakan silang terapkan ke kolom tidakivot ke dalam baris

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
sumber
1
Tidak, saya pikir sama tetapi ini tidak akan berhasil. Bahkan UNIONtidak ada duplikat yang harus dihapus.
ypercubeᵀᴹ
Maksudmu sort tidak bisa dihindari?
Serg
1
Maksud saya itu DISTINCTwajib. Lihat data James. Ada pertengkaran dengan A,B,C,-,-,-dan lain dengan -,-,-,A,B,C. Baris yang dihasilkan satu dari data A dan yang lainnya dari data B adalah identik dan harus dihapus. Bahkan jika UNION ALLdiganti dengan UNION, ini tidak dapat dihindari. (dan dengan "ini" saya tidak bermaksud "sort", maksud saya operasi "berbeda". Ini mungkin dilakukan dengan sortir atau hash, metode apa pun yang dapat dan dipilih oleh pengoptimal.)
ypercubeᵀᴹ