Làm thế nào để truy vấn và tổng hợp một db SQL chuẩn hóa?


7

Liên quan đến cách hiệu quả nhất để trả về nhiều tập hợp trong một lần lưu trữ được lưu trữ?

Tôi có một ứng dụng loại email và muốn chọn tất cả các tin nhắn (hộp thư đến) cho người dùng. Vấn đề là tôi bình thường hóa phần tiêu đề của email vào DB sao cho dữ liệu phẳng đi vào bảng Tin nhắn và từ, đến, CC, BCC được lưu trữ vào một bảng khác.

Cách tốt nhất để chọn thư (đầy đủ - có nghĩa là không chuẩn hóa toàn bộ thư) để mỗi bản ghi chứa tất cả các trường thích hợp của thư bao gồm tất cả các trường của bảng Tin nhắn và mọi bản ghi liên quan từ bảng người nhận liên quan đến tin nhắn theo PK / Mối quan hệ FK.

Một điều tôi đang đặt nặng vấn đề là hiệu quả của giải pháp SQL vì đây sẽ là mã được thực thi nhiều lần và có thể sẽ là sql chạy nhất trong toàn bộ DB

Đối với bối cảnh ở đây là một khung nhìn của lược đồ DB của tôi.

DB SCHema


Bạn mong đợi bao nhiêu dữ liệu trong bảng tin nhắn?
gbn

@gbn: hàng triệu hồ sơ. do đó, ít nhất hai bản ghi cho mỗi bản ghi tin nhắn sẽ có trong bảng người nhận (từ, đến) ở mức tối thiểu.
kacalacco

Bạn có muốn đầu ra của bạn là một chuỗi văn bản duy nhất như email gốc không? Nếu vậy, bạn sẽ cần một số loại tổng hợp chuỗi, chẳng hạn như các phương thức được thảo luận trong câu hỏi SO này
Jack nói hãy thử topanswers.xyz

4
chỉ là tôi hoặc lược đồ này trông quá bình thường?
Mary

@Marian: việc chuẩn hóa là do bảng người nhận có thể chụp các tin nhắn từ triển vọng trong đó một tin nhắn có thể có nhiều danh sách TO, CC và BCC.
kacalacco

Câu trả lời:


6

Đây là cách tôi sẽ làm điều đó. Tôi thường xuyên sử dụng Coalesce để đặt các hàng vào các trường được phân định và nó luôn hoạt động và chia tỷ lệ tốt (miễn là bạn nhận ra rằng một truy vấn phụ là LUÔN LUÔN sẽ gây ra một số hiệu suất).

Nếu bạn không thích chạy nó như một thủ tục được lưu trữ, bạn cũng có thể dễ dàng viết lại dưới dạng hàm có giá trị của bảng.

Một cách tiếp cận khác sẽ là CTE tôi cho rằng nhưng tôi không quen thuộc với cách tiếp cận đó để gõ từ đầu.

CREATE PROCEDURE GetMessageById
    @pMessageID int
AS
BEGIN

SET NOCOUNT ON;

Declare @pTo varchar(max)
Declare @pCC varchar(max)
Declare @pBC varchar(max)

SELECT @pTo = COALESCE(@pTo + ', ', '') + [EmailAddress]
FROM MessageRecipient
WHERE MessageID = @pMessageID AND RecipientTypeID = 1 /** or whatever the id of TO field is */

SELECT @pCC = COALESCE(@pCC + ', ', '') + [EmailAddress]
FROM MessageRecipient
WHERE MessageID = @pMessageID AND RecipientTypeID = 2 /** or whatever the id of CC field is */

SELECT @pBC = COALESCE(@pBC + ', ', '') + [EmailAddress]
FROM MessageRecipient
WHERE MessageID = @pMessageID AND RecipientTypeID = 3 /** or whatever the id of BCC field is */

SELECT Message.*, @pTo as [ToField], @pCC as [CCField], @pBC as [BCCField], (SELECT TOP 1 [EmailAddress] FROM MessageRecipient Where RecipientTypeID = 0 /**<sender id>*/ AND MessageID = @pmessageID) AS [FromField] FROM Message Where Message.ID = @pMessageID

END
GO

Bạn có thể tự hỏi làm thế nào Coalesce hoạt động khi được sử dụng theo cách này (tôi đã làm, khi tôi lần đầu tiên nhìn thấy nó được sử dụng). Về cơ bản, nó tạo ra một truy vấn đệ quy trả về từng giá trị khác không tiếp theo trong tập hợp, cho đến khi kết thúc tập trả về. Đi ra đầu kia, bạn nhận được một danh sách giới hạn hôn mê của tất cả các kết quả dưới dạng một chuỗi.


Chỉ cần có cơ hội để thực sự thử mã này ở nhà và nhận ra tôi cần gỡ lỗi một chút.
RThomas

1
Đó là một mẹo khá gọn gàng với COALESCE. Bạn học cái đó ở đâu?
Michael Riley - AKA Gunny

Ước gì tôi có thể nói rằng tôi đã tự mình tìm ra nhưng than ôi ... Tôi đã tìm thấy một bài báo một thời gian ngắn về các lựa chọn thay thế cho con trỏ. Đây là một trong những thủ thuật được mô tả. Tôi nghĩ rằng đó là một bài viết SqlServerCentral.
RThomas

5

Tôi sẽ tạo một khung nhìn gọi là viewInbox được phát minh bởi tất cả các bảng quan hệ một-một . Đây sẽ là chế độ xem truy vấn chính của tôi. Tôi sẽ sử dụng chế độ xem này (viewInbox) để hiển thị danh sách tất cả các mục trong hộp thư đến.

Khi người dùng đi sâu vào tin nhắn, sau đó tôi sẽ mang lại tất cả thông tin bao gồm các mối quan hệ một-nhiều từ nhiều To, CC và BCC.


Chắc chắn nhiều người thực hiện hơn, và có lẽ tôi cũng sẽ làm như vậy, nhưng không đáp ứng yêu cầu "không chuẩn hóa".
RThomas

2
@LazyDBA - Tôi sẽ coi viewInbox là "không chuẩn hóa".
Michael Riley - AKA Gunny

"Chuẩn hóa" và "không chuẩn hóa" đề cập đến việc thiết kế các bảng. Để không chuẩn hóa một lược đồ có nghĩa là một sự thay đổi đối với lược đồ. Vì vậy, khi có yêu cầu "không chuẩn hóa" dữ liệu bằng cách sử dụng câu lệnh chọn, tôi nghi ngờ từ này đang được sử dụng có nghĩa là "bao gồm dữ liệu dư thừa" về bản chất, nối các bảng vào một tập kết quả.
Michael J Swart
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.