Làm cách nào để làm cho các truy vấn SQL phức tạp dễ viết hơn? [đóng cửa]


42

Tôi thấy rất khó để viết các truy vấn SQL phức tạp liên quan đến các phép nối trên nhiều bảng (ít nhất 3-4) và liên quan đến một số điều kiện lồng nhau. Các truy vấn tôi được yêu cầu viết dễ dàng được mô tả bằng một vài câu, nhưng có thể yêu cầu một lượng mã lừa đảo để hoàn thành. Tôi thấy mình thường sử dụng các chế độ xem tạm thời để viết các truy vấn này, có vẻ như là một cái nạng. Bí quyết nào bạn có thể cung cấp mà tôi có thể sử dụng để làm cho các truy vấn phức tạp này dễ dàng hơn? Cụ thể hơn, làm cách nào để chia các truy vấn này thành các bước tôi cần sử dụng để thực sự viết mã SQL?

Lưu ý rằng tôi là SQL tôi được yêu cầu viết là một phần của bài tập về nhà cho một khóa học cơ sở dữ liệu, vì vậy tôi không muốn phần mềm sẽ làm việc cho tôi. Tôi muốn thực sự hiểu mã tôi đang viết.

Thêm chi tiết kỹ thuật:

  • Cơ sở dữ liệu được lưu trữ trên máy chủ PostgreSQL chạy trên máy cục bộ.
  • Cơ sở dữ liệu rất nhỏ: không có quá bảy bảng và bảng lớn nhất có ít hơn khoảng 50 hàng.
  • Các truy vấn SQL đang được chuyển không thay đổi đến máy chủ, thông qua LibreOffice Base.

Các khung nhìn tạm thời thực sự khá hữu ích vì bạn có thể thực hiện mọi thứ với một bảng như vậy (như các chỉ mục phức tạp rõ ràng) rất khó để gợi ý cho trình phân tích cú pháp SQL.

Cá nhân, tôi thấy việc gian lận dễ dàng hơn bằng cách sử dụng GUI (chẳng hạn như LibreOffice Base "Tạo truy vấn trong dạng xem thiết kế" hoặc Office Access "Tạo"> "Thiết kế truy vấn") và sau đó xem SQL do sản xuất này. Đôi khi cần phải sửa đổi SQL được cung cấp bởi một nhà thiết kế GUI, nhưng nó mang lại một điểm khởi đầu tốt
Kurdtpage

Câu trả lời:


49

Tôi dựa trên hầu hết những điều này chỉ để cố gắng có được câu trả lời "đúng", vì vậy bạn có thể phát hiện ra có một số vấn đề về hiệu suất. Không có điểm trong việc tăng tốc một truy vấn không chính xác.

Hiểu các mối quan hệ bảng - Hầu hết sẽ là một đến nhiều. Biết bảng "nhiều". Xác định các trường cần thiết cho tham gia của bạn.

Hãy suy nghĩ về các kịch bản tham gia TRÁI - Chọn tất cả các nhân viên và tiền lương của họ từ tháng trước. Điều gì sẽ xảy ra nếu họ không nhận được tiền lương vào tháng trước?

Biết tập kết quả: 1) Trong bảng tính, nhập thủ công ít nhất một bản ghi chính xác cho truy vấn của bạn. 2) Viết truy vấn dưới dạng đủ đơn giản để xác định có bao nhiêu bản ghi sẽ được trả về. Sử dụng cả hai cách này để kiểm tra truy vấn của bạn để đảm bảo rằng việc tham gia một bảng mới sẽ không làm thay đổi kết quả.

Chia truy vấn của bạn thành các phần có thể quản lý - Bạn không cần phải viết tất cả cùng một lúc. Các truy vấn phức tạp đôi khi có thể chỉ là một tập hợp các truy vấn đơn giản.

Cảnh giác với các mức tổng hợp hỗn hợp : Nếu bạn phải đặt các giá trị hàng tháng, hàng quý và hàng năm trong cùng một tập kết quả, bạn sẽ cần tính riêng chúng trong các truy vấn được nhóm trên các giá trị khác nhau.

Biết khi nào nên UNION Đôi khi việc chia nhóm con thành các câu lệnh chọn của riêng họ sẽ dễ dàng hơn. Nếu bạn có một bảng được trộn lẫn với người quản lý và các nhân viên khác và trên mỗi cột bạn phải thực hiện các báo cáo trường hợp dựa trên tư cách thành viên trong một trong các nhóm này, có thể dễ dàng hơn để viết truy vấn của người quản lý và kết hợp với truy vấn của nhân viên. Mỗi người sẽ chứa logic riêng của họ. Phải bao gồm các mục từ các bảng khác nhau trong các hàng khác nhau là một cách sử dụng rõ ràng.

Các công thức phức tạp / lồng nhau - Cố gắng liên tục thụt lề và đừng ngại sử dụng nhiều dòng. "TRƯỜNG HỢP KHI TRƯỜNG HỢP KHI TRƯỜNG HỢP KHI NÀO" sẽ khiến bạn phát điên. Hãy dành thời gian để suy nghĩ những điều này thông qua. Lưu các calcs phức tạp cuối cùng. Lấy hồ sơ chính xác được chọn đầu tiên. Sau đó, bạn tấn công các công thức phức tạp khi biết bạn đang làm việc với các giá trị phù hợp. Xem các giá trị được sử dụng trong các công thức sẽ giúp bạn phát hiện ra các khu vực mà bạn phải tính đến các giá trị NULL và nơi xử lý phép chia cho lỗi không.

Kiểm tra thường xuyên khi bạn thêm các bảng mới để đảm bảo bạn vẫn nhận được tập kết quả mong muốn và biết tham gia hoặc mệnh đề nào là thủ phạm.


1
Thứ thực sự tuyệt vời. Tôi muốn nhấn mạnh lại các điểm của Jeff về việc tìm kiếm các tham gia LEFT và chia các truy vấn phức tạp thành các truy vấn nhỏ hơn, dễ quản lý hơn và sau đó kết hợp chúng. Tôi viết các truy vấn lớn trên cơ sở dữ liệu lớn hàng ngày khá nhiều và hai điều đó đặc biệt xuất hiện mọi lúc. Luôn luôn chạy các truy vấn và truy vấn phụ của bạn ngay khi bạn có thể, để đảm bảo bạn sẽ nhận được dữ liệu mà bạn muốn thấy ở mỗi bước.
CodexArcanum

@CodexArcanum - và khi bạn chạy truy vấn trên dữ liệu lớn, sẽ không hại khi sử dụng TOP;)
JeffO

Tôi đồng ý với mọi tuyên bố về đề xuất của bạn
Alessandro Rossi

28
  1. Thụt lề sẽ là điều đầu tiên phải làm, nếu bạn chưa làm điều đó. Không chỉ hữu ích với các truy vấn đơn giản, nhưng nó rất quan trọng khi tham gia và truy vấn phức tạp hơn một chút so với a select top 1 [ColumnName] from [TableName].

  2. Khi đã thụt lề đúng cách, không có gì cấm thêm nhận xét bên trong truy vấn, khi thích hợp. Đừng lạm dụng chúng: nếu mã đủ rõ ràng, việc thêm nhận xét sẽ chỉ gây hại cho sự rõ ràng của mã. Nhưng họ vẫn được chào đón cho các phần ít rõ ràng hơn của truy vấn.

    Lưu ý rằng các truy vấn dài hơn (bao gồm các truy vấn có nhận xét) có nghĩa là việc sử dụng băng thông lớn hơn giữa máy chủ ứng dụng và máy chủ cơ sở dữ liệu của bạn. Cũng lưu ý rằng trừ khi bạn đang làm việc trên một sản phẩm quy mô của Google với số lượng yêu cầu khổng lồ mỗi giây, yêu cầu sử dụng tài nguyên và hiệu suất đặc biệt, kích thước được thêm bởi các nhận xét có thể không thay đổi bất cứ điều gì cho bạn về hiệu suất.

  3. Thực thi cùng một kiểu trên các bảng, cột, vv cũng giúp khả năng đọc rất nhiều. Khi một cơ sở dữ liệu di sản có các bảng PRODUCT, users, USERS_ObsoleteDONT_USE, PR_SHIPMENTSHRhbYd_UU, ai đó đang làm cái gì đó rất sai.

  4. Thực thi cùng một kiểu trên các truy vấn cũng quan trọng. Ví dụ: nếu bạn đang viết truy vấn cho Microsoft SQL Server và bạn đã quyết định sử dụng [TableName]thay vì TableName, hãy gắn bó với nó. Nếu bạn đi đến một dòng mới sau một select, đừng làm điều đó chỉ trong một nửa các truy vấn của bạn, nhưng tất cả chúng.

  5. Không sử dụng* , trừ khi có những lý do mạnh mẽ để làm điều đó (như if exists(select * from [TableName] where ...)trong Microsoft SQL Server). Không chỉ *có tác động hiệu quả tiêu cực trong một số cơ sở dữ liệu (nếu không phải hầu hết), mà còn không hữu ích cho nhà phát triển sử dụng truy vấn của bạn. Theo cùng một cách, một nhà phát triển phải truy cập các giá trị theo tên, không bao giờ theo chỉ mục.

  6. Cuối cùng, đối với các lựa chọn, không có gì sai trong việc cung cấp một khung nhìn . Đối với bất cứ điều gì khác, các thủ tục được lưu trữ cũng có thể được sử dụng tùy thuộc vào dự án và mọi người - bạn đang làm việc với.


Một số người ghét các thủ tục lưu trữ. Những người khác không thích họ vì một số lý do (hoàn toàn hợp lệ, ít nhất là cho họ).

² Đồng nghiệp của bạn, các sinh viên khác, giáo viên của bạn, v.v.


9

Có một chút ảnh chụp trong bóng tối ở đây, nhưng nếu bạn đang viết nhiều chế độ xem tạm thời có lẽ bạn chưa nhận ra rằng hầu hết các vị trí bạn có thể đặt bảng trong câu lệnh SQL, bảng đó có thể được thay thế bằng truy vấn.

Vì vậy, thay vì nối bảng A với chế độ xem tạm thời B, bạn có thể nối bảng A với truy vấn mà bạn đã sử dụng làm chế độ xem tạm thời B. Ví dụ:

    SELECT A.Col1, A.Col2, B.Col1,B.Col2
      FROM (SELECT RealTableZ.Col1, RealTableY.Col2, RealTableY.ID as ID
              FROM RealTableZ 
   LEFT OUTER JOIN RealTableY
                ON RealTableZ.ForeignKeyY=RealTableY.ID
             WHERE RealTableY.Col11>14
            ) As B
        INNER JOIN A
                ON A.ForeignKeyY=B.ID

Ví dụ này khá vô nghĩa, nhưng nên giải thích cú pháp.

Đối với các chế độ xem không "đặc biệt" (được lập chỉ mục, phân vùng), điều này sẽ dẫn đến cùng một kế hoạch truy vấn như khi bạn sử dụng chế độ xem.

Để dễ viết hơn, bạn có thể xác minh từng phần để đảm bảo bạn sẽ nhận được những gì bạn mong đợi trước khi viết ra toàn bộ truy vấn.

Tôi xin lỗi nếu đây là chiếc mũ cũ cho bạn.


3
Tôi khá chuyên gia về SQL và tôi thực sự ghét sự thụt lề này: nó có thể trông đẹp nhưng nó hoàn toàn vô dụng "theo ý kiến ​​của tôi". Hai lý do: Tôi không thể hiểu rõ nếu tham gia bên ngoài bên trái là một phần của truy vấn chính hoặc một phần của truy vấn phụ, nó cần một trình làm đẹp mã và bất cứ khi nào bạn muốn thêm một vài dòng bạn cần làm đẹp lại tất cả văn bản . Kế hoạch thụt lề mà chỉ cần TABS linh hoạt hơn nhiều. Tôi đã không bỏ phiếu cho câu trả lời của bạn nhưng tôi thực sự không khuyến khích bất cứ ai sử dụng phong cách này ... đặc biệt là khi họ cần sự giúp đỡ của tôi.
Alessandro Rossi

7

Thay vì các khung nhìn tạm thời, hãy sử dụng mệnh đề VỚI . Điều này làm cho việc chia nhỏ các truy vấn lớn thành các phần nhỏ dễ đọc hơn dễ dàng hơn nhiều.


1
Nếu bạn sử dụng cte, hãy lưu ý rằng truy vấn chỉ tồn tại cho đến khi truy vấn tiếp theo được chạy, do đó, trong một số trường hợp bạn đang sử dụng cte trong nhiều truy vấn, có thể tốt hơn khi sử dụng bảng tạm thời.
Rachel

3
  1. Làm quen với lý thuyết tập hợp nếu bạn chưa có. SQL dựa trên lý thuyết tập hợp và hiểu thêm về các tập hợp sẽ giúp bạn làm quen với cách SQL hoạt động.
  2. Thực hành nhiều hơn nữa, nếu bạn chỉ học SQL, sẽ mất thời gian để hiểu cách làm mọi thứ, đôi khi chỉ cần thời gian trước khi bạn thực sự hiểu chúng, Joins là một ví dụ tuyệt vời khi bạn sử dụng chúng càng tốt, bạn sẽ càng hiểu rõ về nó.
  3. Đảm bảo các bảng bạn đang truy vấn được thiết kế đúng
  4. Đừng sợ sử dụng chế độ xem trên các truy vấn chọn, đặc biệt nếu bạn có một bộ chung cần được tinh chỉnh theo nhiều cách khác nhau

1

Giống như bất cứ điều gì khác, bạn muốn chia vấn đề thành các phần có thể quản lý được.

Đó thực sự là cách bạn giải quyết các vấn đề phức tạp.

Vì vậy: Bạn muốn kiểm tra truy vấn con để thấy rằng nó thực sự trả về những gì bạn muốn trước khi chạy một truy vấn bên ngoài trên nó. Bạn muốn thử tham gia tối thiểu của mỗi bảng bạn đang tham gia để bạn có thể thấy rằng bạn thực sự nghĩ về nó đúng cách. Đại loại như thế. Hy vọng gõ tất cả vào và lấy ra chính xác những gì bạn muốn trong một cú đánh là không thực tế.

Một câu lệnh SQL, một khi nó đạt đến một mức độ phức tạp nhất định, về cơ bản là một chương trình nhỏ. Nó tạo ra sự khác biệt lớn để thực sự hiểu cách dữ liệu được kết hợp, lựa chọn, lọc và đầu ra.

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.