Laravel Eloquent tính tổng hai cột

Bạn không cần sử dụng

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
6 vì bạn không nối hai bảng nên bạn có thể cần tham chiếu bảng

Vui lòng tìm tài liệu tham khảo tại đây

Giải pháp liên quan

Php – Cách ngăn SQL injection trong PHP

Cách chính xác để tránh các cuộc tấn công SQL injection, bất kể bạn sử dụng cơ sở dữ liệu nào, là tách dữ liệu khỏi SQL, để dữ liệu vẫn là dữ liệu và sẽ không bao giờ được trình phân tích cú pháp SQL diễn giải thành các lệnh. Có thể tạo câu lệnh SQL với các phần dữ liệu được định dạng chính xác, nhưng nếu bạn không hiểu đầy đủ chi tiết, bạn nên luôn sử dụng câu lệnh đã chuẩn bị sẵn và truy vấn được tham số hóa. Đây là các câu lệnh SQL được máy chủ cơ sở dữ liệu gửi đến và phân tích cú pháp riêng biệt với bất kỳ tham số nào. Bằng cách này, kẻ tấn công không thể tiêm SQL độc hại

Về cơ bản, bạn có hai lựa chọn để đạt được điều này

  1. Sử dụng PDO [đối với mọi trình điều khiển cơ sở dữ liệu được hỗ trợ]

     $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];
    
     $stmt->execute[[ 'name' => $name ]];
    
     foreach [$stmt as $row] {
         // Do something with $row
     }
    
  2. Sử dụng MySQLi [dành cho MySQL]

     $stmt = $dbConnection->prepare['SELECT * FROM employees WHERE name = ?'];
     $stmt->bind_param['s', $name]; // 's' specifies the variable type => 'string'
    
     $stmt->execute[];
    
     $result = $stmt->get_result[];
     while [$row = $result->fetch_assoc[]] {
         // Do something with $row
     }
    

Nếu bạn đang kết nối với cơ sở dữ liệu không phải MySQL, thì có tùy chọn thứ hai dành riêng cho trình điều khiển mà bạn có thể tham khảo [ví dụ:

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
7 và
+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
8 cho PostgreSQL]. PDO là tùy chọn phổ quát

Thiết lập kết nối chính xác

Lưu ý rằng khi sử dụng PDO để truy cập cơ sở dữ liệu MySQL, các câu lệnh chuẩn bị thực không được sử dụng theo mặc định. Để khắc phục điều này, bạn phải tắt mô phỏng các câu lệnh đã chuẩn bị. Một ví dụ về việc tạo kết nối bằng PDO là

$dbConnection = new PDO['mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'password'];

$dbConnection->setAttribute[PDO::ATTR_EMULATE_PREPARES, false];
$dbConnection->setAttribute[PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION];

Trong ví dụ trên, chế độ lỗi không thực sự cần thiết, nhưng bạn nên thêm nó vào. Bằng cách này, tập lệnh sẽ không dừng lại với

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
9 khi có sự cố xảy ra. Và nó mang lại cho nhà phát triển cơ hội
$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
0 bất kỳ [các] lỗi nào
$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
1n thành
$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
2

Tuy nhiên, điều bắt buộc là dòng

$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
3 đầu tiên, yêu cầu PDO tắt các câu lệnh đã chuẩn bị được mô phỏng và sử dụng các câu lệnh đã chuẩn bị thực sự. Điều này đảm bảo câu lệnh và các giá trị không được PHP phân tích cú pháp trước khi gửi nó đến máy chủ MySQL [khiến kẻ tấn công không có cơ hội tiêm SQL độc hại]

Mặc dù bạn có thể đặt

$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
4 trong các tùy chọn của hàm tạo, điều quan trọng cần lưu ý là các phiên bản PHP 'cũ' [trước 5. 3. 6] âm thầm bỏ qua tham số bộ ký tự trong DSN

Giải trình

Câu lệnh SQL bạn chuyển đến

$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
5 được máy chủ cơ sở dữ liệu phân tích cú pháp và biên dịch. Bằng cách chỉ định tham số [có thể là
$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
6 hoặc tham số được đặt tên như
$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
7 trong ví dụ trên], bạn cho công cụ cơ sở dữ liệu biết nơi bạn muốn lọc. Sau đó, khi bạn gọi
$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
8, câu lệnh đã chuẩn bị được kết hợp với các giá trị tham số mà bạn chỉ định

Điều quan trọng ở đây là các giá trị tham số được kết hợp với câu lệnh đã biên dịch, không phải là chuỗi SQL. SQL injection hoạt động bằng cách lừa tập lệnh bao gồm các chuỗi độc hại khi nó tạo SQL để gửi đến cơ sở dữ liệu. Vì vậy, bằng cách gửi SQL thực riêng biệt với các tham số, bạn sẽ hạn chế rủi ro kết thúc bằng thứ mà bạn không có ý định

Bất kỳ tham số nào bạn gửi khi sử dụng câu lệnh đã chuẩn bị sẽ chỉ được coi là chuỗi [mặc dù công cụ cơ sở dữ liệu có thể thực hiện một số tối ưu hóa để tất nhiên, tham số cũng có thể kết thúc dưới dạng số]. Trong ví dụ trên, nếu biến

$result = DB::table['daily as d']
                ->select[[
                    'excavatorId',
                    'times_loaded',
                    'litres'
                ]]
              ->groupBy['excavatorId']
              ->where['date', $request->input['date']]
              ->sum['d.times_loaded', 'd.litres'];
9 chứa
 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
70, kết quả sẽ chỉ là tìm kiếm chuỗi
 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
71 và bạn sẽ không nhận được một bảng trống

Một lợi ích khác của việc sử dụng các câu lệnh đã chuẩn bị là nếu bạn thực hiện cùng một câu lệnh nhiều lần trong cùng một phiên thì nó sẽ chỉ được phân tích cú pháp và biên dịch một lần, giúp bạn tăng tốc độ

Ồ, và vì bạn đã hỏi về cách thực hiện cho phần chèn, đây là một ví dụ [sử dụng PDO]

 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
9

Câu lệnh đã chuẩn bị có thể được sử dụng cho các truy vấn động không?

Mặc dù bạn vẫn có thể sử dụng các câu lệnh đã chuẩn bị cho các tham số truy vấn, nhưng bản thân cấu trúc của truy vấn động không thể được tham số hóa và một số tính năng truy vấn nhất định không thể được tham số hóa

Đối với những trường hợp cụ thể này, điều tốt nhất cần làm là sử dụng bộ lọc danh sách trắng để hạn chế các giá trị có thể

 $stmt = $dbConnection->prepare['SELECT * FROM employees WHERE name = ?'];
 $stmt->bind_param['s', $name]; // 's' specifies the variable type => 'string'

 $stmt->execute[];

 $result = $stmt->get_result[];
 while [$row = $result->fetch_assoc[]] {
     // Do something with $row
 }
0

Mysql – Truy xuất bản ghi cuối cùng trong mỗi nhóm – MySQL

Mysql 8. 0 hiện hỗ trợ các chức năng cửa sổ, giống như hầu hết các triển khai SQL phổ biến. Với cú pháp tiêu chuẩn này, chúng ta có thể viết truy vấn n-mỗi-nhóm lớn nhất

 $stmt = $dbConnection->prepare['SELECT * FROM employees WHERE name = ?'];
 $stmt->bind_param['s', $name]; // 's' specifies the variable type => 'string'

 $stmt->execute[];

 $result = $stmt->get_result[];
 while [$row = $result->fetch_assoc[]] {
     // Do something with $row
 }
1

Dưới đây là câu trả lời gốc tôi đã viết cho câu hỏi này vào năm 2009

Tôi viết giải pháp theo cách này

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
0

Về hiệu suất, giải pháp này hay giải pháp kia có thể tốt hơn, tùy thuộc vào bản chất dữ liệu của bạn. Vì vậy, bạn nên kiểm tra cả hai truy vấn và sử dụng truy vấn có hiệu suất tốt hơn với cơ sở dữ liệu của bạn

Ví dụ: tôi có một bản sao của kết xuất dữ liệu tháng 8 của StackOverflow. Tôi sẽ sử dụng nó để đo điểm chuẩn. Có 1.114.357 hàng trong bảng

 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
72. Cái này đang chạy trên MySQL 5. 0. 75 trên Macbook Pro 2 của tôi. 40GHz

Tôi sẽ viết một truy vấn để tìm bài đăng gần đây nhất cho một ID người dùng nhất định [của tôi]

Lần đầu tiên sử dụng kỹ thuật được hiển thị bởi @Eric với

 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
73 trong truy vấn con

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
1

Ngay cả phân tích

 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
74 cũng mất hơn 16 giây

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
2

Bây giờ, hãy tạo kết quả truy vấn tương tự bằng cách sử dụng kỹ thuật của tôi với

 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
75

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
3

Phân tích

 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
74 cho thấy cả hai bảng đều có thể sử dụng chỉ mục của chúng

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
4

Đây là DDL cho bảng

 $stmt = $pdo->prepare['SELECT * FROM employees WHERE name = :name'];

 $stmt->execute[[ 'name' => $name ]];

 foreach [$stmt as $row] {
     // Do something with $row
 }
72 của tôi

+-------------+-------------------+-------------+
| excavatorId | sum[times_loaded] | sum[litres] |
+-------------+-------------------+-------------+
|          55 |               179 |         168 |
|          60 |                50 |          50 |
+-------------+-------------------+-------------+
5

Lưu ý cho người bình luận. Nếu bạn muốn một điểm chuẩn khác với phiên bản MySQL khác, tập dữ liệu khác hoặc thiết kế bảng khác, vui lòng tự làm điều đó. Tôi đã chỉ ra kỹ thuật trên. Stack Overflow ở đây để chỉ cho bạn cách thực hiện công việc phát triển phần mềm chứ không phải để làm tất cả công việc cho bạn

Chủ Đề