Có cách nào để thực hiện lựa chọn này lấy kết quả tương tự với một lần tìm kiếm không?


8

Có thể truy xuất cùng một dữ liệu như sau với một lần tìm kiếm hoặc quét, bằng cách sửa đổi truy vấn hoặc ảnh hưởng đến chiến lược của trình tối ưu hóa không?

Mã và lược đồ tương tự như hiện đang có trên SQL Server 2014.

nhập mô tả hình ảnh ở đây

Kịch bản repro. Thiết lập:

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

Truy vấn:

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;

Phá bỏ:

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

Tôi nghĩ rằng điều này có thể không được mô hình hóa lý tưởng. Tôi đang cố gắng để có thêm thông tin từ nhà phát triển về cách chọn lược đồ nhưng tôi tò mò liệu có một thủ thuật TSQL nào tôi đang xem vì sẽ dễ dàng thay đổi truy vấn hơn lược đồ.

Câu trả lời:


6

Tôi sẽ thử điều này nhưng tôi không biết nó sẽ hiệu quả hơn. Bạn cần DISTINCTloại bỏ trùng lặp, vì vậy UNION ALLcó thể phù hợp hơn, không cần hai thao tác riêng biệt:

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 kế hoạch:

ĐOÀN TẤT CẢ kế hoạch

UNION kế hoạch:

Kế hoạch của UNION


3

Sử dụng chéo áp dụng cho các cột không liên kết thành các hàng

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
Không, tôi cũng nghĩ như vậy nhưng điều này sẽ không hiệu quả. Ngay cả với UNIONnhững bản sao phải được loại bỏ.
ypercubeᵀᴹ

Bạn có nghĩa là sắp xếp là không thể tránh khỏi?
Serg

1
Ý tôi là điều đó DISTINCTlà bắt buộc. Xem dữ liệu của James. Có một hàng với A,B,C,-,-,-và khác với -,-,-,A,B,C. Các hàng kết quả một từ dữ liệu A và hàng khác từ dữ liệu B là giống hệt nhau và phải được loại bỏ. Ngay cả khi UNION ALLđược thay thế bằng UNION, điều này không thể tránh được. (và với "this" Tôi không có nghĩa là "sort", ý tôi là thao tác "khác biệt". Nó có thể được thực hiện với sort hoặc băm, bất cứ phương thức nào trình tối ưu hóa có thể và chọn.)
ypercubeᵀᴹ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.