Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

So sánh hai phạm vi ngày trong cùng một bảng

Sử dụng IBM Informix Dynamic Server 11.50.FC6, tôi có thể sử dụng chuỗi SQL này để nhận được kết quả bạn yêu cầu:

Thiết lập

CREATE TABLE sales
(
    id       INTEGER NOT NULL,
    id_store INTEGER NOT NULL,
    date     DATE NOT NULL,
    total    DECIMAL(10,2) NOT NULL
);

INSERT INTO sales VALUES( 1, 1, '2010-01-01', 500.00);
INSERT INTO sales VALUES( 2, 1, '2010-01-02', 185.00);
INSERT INTO sales VALUES( 3, 1, '2010-01-03', 135.00);
INSERT INTO sales VALUES( 4, 1, '2009-01-01', 165.00);
INSERT INTO sales VALUES( 5, 1, '2009-01-02', 175.00);
INSERT INTO sales VALUES( 6, 5, '2010-01-01', 130.00);
INSERT INTO sales VALUES( 7, 5, '2010-01-02', 135.00);
INSERT INTO sales VALUES( 8, 5, '2010-01-03', 130.00);
INSERT INTO sales VALUES( 9, 6, '2010-01-01', 100.00);
INSERT INTO sales VALUES(10, 6, '2010-01-02',  12.00);
INSERT INTO sales VALUES(11, 6, '2010-01-03',  85.00);
INSERT INTO sales VALUES(12, 6, '2009-01-01', 135.00);
INSERT INTO sales VALUES(13, 6, '2009-01-02', 400.00);
INSERT INTO sales VALUES(14, 6, '2009-01-07',  21.00);
INSERT INTO sales VALUES(15, 6, '2009-01-08',  45.00);
INSERT INTO sales VALUES(16, 8, '2009-01-09', 123.00);
INSERT INTO sales VALUES(17, 8, '2009-01-10', 581.00);

Truy vấn

SELECT *
  FROM (SELECT s1.id AS s1id,
               NVL(s1.id_store, s2.id_store) AS s1store,
               NVL(s1.date, MDY(MONTH(s2.date), DAY(s2.date),
                                YEAR(s2.date)+1)) AS s1date,
               s1.total AS s1total,
               s2.id AS s2id,
               NVL(s2.id_store, s1.id_store) AS s2store,
               NVL(s2.date, MDY(MONTH(s1.date), DAY(s1.date),
                                YEAR(s1.date)-1)) AS s2date,
               s2.total AS s2total
          FROM sales AS s1 FULL JOIN sales AS s2
            ON s1.id_store = s2.id_store
           AND s1.date BETWEEN '2010-01-01' AND '2010-01-10'
           AND s2.date BETWEEN '2009-01-01' AND '2009-01-10'
           AND DAY(s1.date)   = DAY(s2.date)
           AND MONTH(s1.date) = MONTH(s2.date)
       ) AS s3
 WHERE s1_date BETWEEN '2010-01-01' AND '2010-01-10'
   AND s2_date BETWEEN '2009-01-01' AND '2009-01-10'
 ORDER BY s1_id_store ASC, s1_date ASC;

Kết quả

s1id s1store  s1date     s1total  s2id s2store  s2date     s2total
 1       1    2010-01-01  500.00   4       1    2009-01-01  165.00
 2       1    2010-01-02  185.00   5       1    2009-01-02  175.00
 3       1    2010-01-03  135.00           1    2009-01-03             
 6       5    2010-01-01  130.00           5    2009-01-01             
 7       5    2010-01-02  135.00           5    2009-01-02             
 8       5    2010-01-03  130.00           5    2009-01-03             
 9       6    2010-01-01  100.00  12       6    2009-01-01  135.00
10       6    2010-01-02   12.00  13       6    2009-01-02  400.00
11       6    2010-01-03   85.00           6    2009-01-03             
         6    2010-01-07          14       6    2009-01-07   21.00
         6    2010-01-08          15       6    2009-01-08   45.00
         8    2010-01-09          16       8    2009-01-09  123.00
         8    2010-01-10          17       8    2009-01-10  581.00

Giải thích

Phải mất rất nhiều thử nghiệm để có được điều này 'đúng'. Informix có hàm tạo DATE MDY () nhận ba đối số nguyên:tháng, ngày và năm (tên là mnemonic). Nó cũng có ba hàm phân tích:DAY (), MONTH () và YEAR () trả về ngày, tháng và năm của đối số ngày. Truy vấn bên trong với FULL JOIN cung cấp cho bạn kết quả với giá trị rỗng ở cả hai bên trái và phải. Tiêu chí 5 phần trong điều khoản BẬT dường như là cần thiết; nếu không, các tiêu chí trong truy vấn bên ngoài phải phức tạp hơn và khó hiểu hơn - nếu nó có thể hoạt động được. Sau đó, các tiêu chí trong lựa chọn bên ngoài đảm bảo rằng dữ liệu phù hợp được chọn. Một lợi thế của biểu thức NVL () trong truy vấn bên trong là các cột ID cửa hàng đều giống nhau chứ không phải giá trị rỗng và cả cột ngày tháng đều không giá trị, vì vậy thứ tự theo mệnh đề có thể đơn giản hơn - trên ID cửa hàng và cột ngày tháng.

Trong Informix, cũng có thể làm lại các biểu thức ngày tháng như:

NVL(s1.date, s2.date + 1 UNITS YEAR)
NVL(s2.date, s1.date - 1 UNITS YEAR)

Trên thực tế, có nhiều chuyển đổi kiểu diễn ra đằng sau với ký hiệu đó, nhưng nó mang lại cho bạn kết quả tương tự và việc tính toán thêm có lẽ không phải là tất cả những gì đáng kể.

Cũng có một trục trặc trong việc chờ đợi trong Informix; bạn không thể cộng hoặc trừ 1 năm vào hoặc từ bất kỳ ngày 29 tháng 2 nào - vì không có ngày 29 tháng 2 trong năm sau hoặc năm trước. Bạn sẽ cần phải cẩn thận với dữ liệu của mình; nếu không, cuối cùng bạn có thể so sánh dữ liệu cho 2008-02-29 với 2009-02-28 (cũng như so sánh dữ liệu cho 2008-02-28 với 2009-02-28). Có một quy trình được gọi là 'kế toán hai lần', nhưng đây không phải là ý nghĩa của nó và việc tính toán của bạn có thể bị nhầm lẫn nếu '2008-02-29 cộng với 1 năm' là 2009-02-28. Informix tạo ra một lỗi; điều đó không hữu ích hơn nhiều. Bạn có thể viết mã một thủ tục được lưu trữ, có thể, để trả về NULL cho 2008-02-29 cộng với 1 năm vì không có ngày nào để so sánh doanh số bán hàng của nó với.

Bạn sẽ có thể thích ứng số học ngày tháng với MySQL khá dễ dàng; phần còn lại của mã không cần thay đổi.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chuyển các tham số cho tập lệnh MySQL

  2. NHÓM MySQL Theo số lượng

  3. Chỉ cập nhật trường MYSQL nếu trường chứa null hoặc 0

  4. Khắc phục khoảng trống trong id hàng bảng mysql sau khi chúng tôi xóa một số trong số chúng

  5. Ràng buộc duy nhất cho phép các giá trị trống trong MySQL