Cập nhật mệnh đề WHERE để kiểm tra xem giá trị KHÔNG ở trong một bảng riêng biệt


8

Tôi có một truy vấn sử dụng WHEREmệnh đề và tôi tình cờ sử dụng chính xác WHEREmệnh đề đó trong nhiều truy vấn trên bảng này (et al).

Truy vấn là:

SELECT
    DATENAME(DW, [AtDateTime]) AS [Day of Week]
    ,COUNT(*) AS [Number of Searches]
    ,CAST(CAST(COUNT(*) AS DECIMAL(10, 2)) 
         / COUNT(DISTINCT CONVERT(DATE, [AtDateTime])) AS DECIMAL(10, 2)) 
       AS [Average Searches per Day]
    ,SUM(CASE WHEN [NumFound] = 0 THEN 1 ELSE 0 END) 
       AS [Number of Searches with no Results]
    ,CAST(CAST(SUM(CASE WHEN [NumFound] = 0 THEN 1 ELSE 0 END) 
         AS DECIMAL(10, 2)) / COUNT(*) AS DECIMAL(10, 4)) 
       AS [Percent of Searches with no Results]
FROM [DB].[dbo].[SearchHistory] 
WHERE 
    [CustomerNumber] <> '1234' AND [CustomerNumber] <> '5678'
GROUP BY DATENAME(DW, [AtDateTime]), DATEPART(DW, [AtDateTime])
ORDER BY DATEPART(DW, [AtDateTime])

Phần tôi muốn thay đổi là WHEREmệnh đề, thay vào đó cho phép tôi sử dụng bảng để nếu tôi phải thêm số khách hàng bị bỏ qua, tôi không phải cập nhật tất cả các truy vấn của mình. (Và có khá nhiều truy vấn có cùng WHEREmệnh đề này.)


Nếu các loại trừ của Khách hàng hiện cụ thể đối với việc thực hiện truy vấn, tại sao việc chuyển chúng sang bảng chia sẻ / bảng làm việc không đưa ra chia sẻ sai? Trong một ứng dụng thông thường, khách hàng thường sẽ tùy ý & do đó cụ thể cho một lần thực hiện truy vấn. Tôi sẽ đề nghị câu hỏi này hoặc bỏ qua các sự kiện quan trọng như tính tổng quát cần thiết để giải pháp hoạt động chính xác hoặc bỏ qua vấn đề chia sẻ.
Thomas W

@ThomasW - "chia sẻ sai" này bạn đang nói về cái gì? Bạn có một tài liệu tham khảo cho điều đó? Tôi chưa bao giờ nghe nói về nó trước đây.
Max Vernon

1
@ThomasW Các yêu cầu cho điều này là một số khách hàng nhất định mà chúng tôi có (mà chúng tôi sử dụng rất nhiều để thử nghiệm) phải được loại trừ khỏi các báo cáo nhất định, vì chúng làm sai lệch kết quả.
Der Kommissar

1
@MaxVernon - có lẽ một thuật ngữ được công nhận tốt hơn sẽ là "phạm vi không chính xác". Những gì được mô tả đã liên quan đến việc thay đổi một đầu vào từ một tham số hoàn toàn độc lập, thành một bảng DB chia sẻ nhiều người dùng, gọi chéo. Sự thay đổi này vượt qua 2 ranh giới phạm vi. Với bối cảnh bổ sung, phạm vi được mô tả có vẻ ổn, nhưng nếu không, điều này sẽ biểu hiện là "chia sẻ sai lầm".
Thomas W

1
Cách tiếp cận được mô tả cũng gợi nhớ đến toàn bộ quá trình thực hiện bảng công việc kế thừa (~ 1000 bảng) trong một ứng dụng chính mà tôi chịu trách nhiệm. Về vấn đề này, tôi đã nêu ra bản chất "bàn làm việc" có thể như một câu hỏi :) Cảm ơn.
Thomas W

Câu trả lời:


5

Tạo một bảng để giữ các số khách hàng được loại trừ, sau đó loại trừ các hàng đó bằng cách sử dụng a NOT EXISTStrong WHEREmệnh đề.

CREATE TABLE dbo.ExcludedCustomers
(
    CustomerNumber VARCHAR(255) NOT NULL
        CONSTRAINT PK_ExcludedCustomers
        PRIMARY KEY CLUSTERED
);

INSERT INTO dbo.ExcludedCustomers (CustomerNumber)
VALUES ('1234')
    , ('5678');


SELECT
    <....>
FROM [DB].[dbo].[SearchHistory] 
WHERE 
    NOT EXISTS (
        SELECT 1
        FROM dbo.ExcludedCustomers ec
        WHERE ec.CustomerNumber = SearchHistory.CustomerNumber
    )
    <...>;

7
CREATE TABLE dbo.CustomerExclusions
(
  CustomerNumber VARCHAR(32) PRIMARY KEY -- Is CustomerNumber *really* a string?
);

INSERT dbo.CustomerExclusions(CustomerNumber) VALUES('1234'),('5678');

Bây giờ WHEREmệnh đề của bạn trên tất cả các truy vấn trở thành:

WHERE NOT EXISTS 
(
  SELECT 1 FROM dbo.CustomerExclusions AS c
  WHERE c.CustomerNumber = SearchHistory.CustomerNumber
)

Vâng, thật không may. Số khách hàng phải là một chuỗi để tương thích chéo với AS / 400. (Ít nhất là bây giờ, chúng tôi đang tiến hành sửa lỗi.)
Der Kommissar

3
@EBrown Uh, ugh.
Aaron Bertrand

-3

Có những câu hỏi quan trọng / vấn đề tiềm năng với phương pháp đề xuất của bạn. Để chắc chắn, bạn có thể loại trừ đủ dễ dàng thông qua bảng làm việc 'Loại trừ số lượng khách hàng':

WHERE NOT EXISTS (
  SELECT 1 FROM [dbo].Work_ExcludeCustomer
  WHERE CustomerNumber = SearchHistory.CustomerNumber
)

Nhưng bây giờ, "tham số truy vấn" là gì - hoàn toàn năng động & độc lập, mỗi truy vấn và mỗi người dùng - đang chuyển thành "trạng thái liên tục được chia sẻ trong cơ sở dữ liệu".

Một số câu hỏi và điểm liên quan:

  1. thông tin Loại trừ khách hàng nên tách biệt, mỗi người dùng hoặc mỗi phiên? bạn có thể thêm một tham số 'SessionID' để phân biệt các tham số này, nhưng về cơ bản, bạn đang tạo lại một mẫu "Bảng công việc" cũ.

  2. có lẽ một mệnh đề KHÔNG IN (...) có thể thích hợp hơn? có thể được tham số hóa động, lên đến giới hạn 2100 tham số.

  3. có thể xem lại mã / cơ sở hạ tầng của bạn để xây dựng các truy vấn & liên kết các tham số, nếu bạn hiện đang dựa vào số tham số cố định; cải thiện điều này sẽ cho phép mô đun hóa và sử dụng mệnh đề IN hoặc KHÔNG IN (?,?,? ..) với số lượng tham số thay đổi.

Đề xuất phương pháp:

WHERE [CustomerNumber] NOT IN (?, ?, ?)

Với các liên kết '1234', '5678', '6789', v.v. với các tham số NOT IN () và các tham số truy vấn logic tiếp theo được liên kết với cách đánh số thích hợp.


1
Việc sử dụng NOT IN (...) và / hoặc tự động xây dựng văn bản truy vấn là một kiểu chống mẫu và sẽ dẫn đến hiệu suất thấp hơn các cách tiếp cận dựa trên tập hợp được đề xuất bởi Aaron và bản thân tôi.
Max Vernon

Đối với một đọc tuyệt vời về sự khác biệt, kiểm tra bài này .
Max Vernon

@MaxVernon - thay thế các tham số động bằng dữ liệu "bảng chia sẻ" hoặc bảng công việc có thể đưa ra chia sẻ sai, điều này vượt xa so với mô hình chống. Vì không ai khác đã xem xét hoặc xác định cụ thể rằng đây không phải là vấn đề, nên hoàn toàn hợp lệ để nêu lên mối quan tâm này; cũng không nên bỏ phiếu tầm thường.
Thomas W
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.