2011-10-24 16 views
5

theo tất cả các mẫu, chuyển đổi SQL để LINQ cho HAVING khoản như trong ví dụ này:LINQ to SQL GROUP BY HAVING tạo ra chỉ như là subquery

SELECT NAME 
FROM TABLES 
GROUP BY NAME 
HAVING COUNT(*) > 1 

là: (vb.net)

from t in tables 
group t by t.NAME into g = Group 
where g.count > 1 
select g 

NHƯNG tuyên bố LINQ trên được phiên dịch sang các SQL sau:


SELECT [t1].[NAME] AS [Key] 
FROM (
    SELECT COUNT(*) AS [value], [t0].[NAME] 
    FROM [tables] AS [t0] 
    WHERE [t0].[NAME] <> @p0 
    GROUP BY [t0].[NAME] 
    ) AS [t1] 
WHERE [t1].[value] > @p1 

Tôi chưa bao giờ thành công trong việc tạo biểu mẫu HAVING LINQ. Giả sử HAVING và nhóm truy vấn con bằng WHERE tương đương với kết quả, nhưng có sự khác biệt về hiệu suất không? những gì về việc giữ các truy vấn SQL ban đầu của tôi ít nhất là SIMILAR với các truy vấn LINQ tạo ra cơ bản?

Trả lời

4

Bạn có thể chứng minh xem liệu hai truy vấn được đề cập có được thực thi cùng một kiểu bởi SQL Server hay không bằng cách xem Kế hoạch thực thi. Lấy mã kiểm tra sau (tôi đã sử dụng SQL Server 2008):

CREATE TABLE #TABLES ([ID] INT IDENTITY, [Name] VARCHAR(30)) 
INSERT INTO #TABLES VALUES('A') 
INSERT INTO #TABLES VALUES('A') 
INSERT INTO #TABLES VALUES('B') 
INSERT INTO #TABLES VALUES('C') 
INSERT INTO #TABLES VALUES('D') 

SELECT NAME 
FROM #TABLES 
WHERE [Name] <> 'D' 
GROUP BY NAME 
HAVING COUNT(*) > 1 

SELECT [t1].[NAME] 
FROM (
    SELECT COUNT(*) AS [value], [t0].[NAME] 
    FROM [#TABLES] AS [t0] 
    WHERE [t0].[NAME] <> 'D' 
    GROUP BY [t0].[NAME] 
    ) AS [t1] 
WHERE [t1].[value] > 1 

DROP TABLE #TABLES 

Thực thi các truy vấn từ SQL Query Analyzer với "Bao gồm Kế hoạch thực hiện thực tế" được chọn trong menu "Truy vấn" sẽ mang lại kết quả như sau:

execution plans

Trong trường hợp này, vì các kế hoạch truy vấn được tạo giống hệt nhau, chắc chắn sẽ không có sự khác biệt hiệu năng giữa SQL và SQL được tạo từ câu lệnh LINQ của bạn. Là một lưu ý phụ, không may, tôi không thể tìm thấy bất kỳ tài liệu nào về lý do tại sao LinqToSql không sử dụng HAVING, hoặc nếu sử dụng HAVING so với sử dụng một lựa chọn phụ mang lại hiệu suất một cách này hay cách khác. Nếu tôi phải đoán tôi muốn nói trình tối ưu hóa truy vấn trong SQL Server chuyển nội bộ các câu lệnh này thành cùng một truy vấn trước khi chúng được thực hiện, đó là lý do tại sao các Kế hoạch thực thi giống nhau cho cả hai câu lệnh. Có hay không tuyên bố trước của tôi là đúng, tôi sẽ nói rằng nếu bạn đang bao giờ nghi ngờ, chỉ cần kiểm tra các kế hoạch thực hiện cho phiên bản SQL của bạn so với phiên bản LinqToSql. Nếu chúng giống nhau thì bạn không có gì phải lo lắng về hiệu năng. Nếu phiên bản SQL của bạn hiệu quả hơn nhiều, thì bạn luôn có thể viết một thủ tục lưu sẵn và chỉ cần gọi thủ tục đã lưu trữ bằng cách sử dụng LinqToSql.