2011-11-25 42 views
5

Đây là dữ liệuChọn một hàng với giá trị riêng biệt của một cột

id name  start_date end_date merchant_id 
=================================================== 
111 name1 25-nov-11 31-jan-12 9999 
222 name2 23-nov-11 25-dec-11 9999 
333 name3 25-nov-11 25-nov-12 9999 
444 name4 20-nov-11 20-nov-11 9999 
555 name5 25-nov-11 25-dec-11 8888 
666 name6 19-oct-11 20-nov-11 8888 
777 name7 20-nov-11 20-jun-12 8888 

tôi cần để có được tất cả các hàng sắp xếp theo start_date (desc), nơi start_date<=todayend_date >=today nhưng giới hạn 1 mỗi merchant_id. Điều đó có nghĩa là nếu truy vấn tìm thấy nhiều hàng, thì chỉ cần trả lại hàng đầu tiên.


thử nghiệm kịch bản

CREATE TABLE DEAL 
(
    ID   VARCHAR2(40 BYTE)  NOT NULL, 
    NAME   VARCHAR2(255 BYTE), 
    START_DATE DATE, 
    END_DATE  DATE, 
    MERCHANT_ID NUMBER(22), 
CONSTRAINT DEAL PRIMARY KEY (ID) 
); 

INSERT ALL 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('111','name1','25-nov-11','31-jan-12','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('222','name2','23-nov-11','25-dec-11','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('333','name3','25-nov-11','25-nov-12','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('444','name4','20-nov-11','20-nov-11','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('555','name5','25-nov-11','25-dec-11','8888') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('666','name6','19-oct-11','20-nov-11','8888') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('777','name7','20-nov-11','20-jun-12','8888') 
SELECT * FROM dual; 

chạy này:

SELECT DISTINCT merchant_id, id, name, start_date, end_date FROM deal WHERE start_date <= trunc(sysdate) AND end_date >= trunc(sysdate) ORDER BY start_date DESC; 

không trả lại kết quả mong muốn như id thương tương tự được trả lại nhiều lần:

MERCHANT_ID ID NAME START_DATE END_DATE 
=========================================== 
9999   111 name1 25-NOV-11 31-JAN-12 
9999   333 name3 25-NOV-11 25-NOV-12 
8888   555 name5 25-NOV-11 25-DEC-11 
9999   222 name2 23-NOV-11 25-DEC-11 
8888   777 name7 20-NOV-11 20-JUN-12 
+0

bạn có thể sử dụng GIỮA khoản thay vì start_date <= hôm nay và end_date> = ngày hôm nay. –

+0

Tôi đã thử nhiều câu khác nhau, giới hạn, nhóm theo .. nhưng không thể làm được bất kỳ việc gì. Tôi có thể nhận được tất cả các hàng có ngày bắt đầu và ngày kết thúc phù hợp nhưng không biết cách trả lại 1 hàng cho mỗi merchant_id –

+0

Bạn đang sử dụng cơ sở dữ liệu nào? nếu bạn đang sử dụng Oracle một giải pháp là sử dụng chức năng phân tích – Giovanni

Trả lời

2

Truy vấn Oracle sau nên làm những gì bạn cần:

SELECT * 
FROM (
    SELECT TABLE1.*, DENSE_RANK() OVER(PARTITION BY MERCHANT_ID ORDER BY START_DATE DESC, ID) R 
    FROM TABLE1 
    WHERE SYSDATE BETWEEN START_DATE AND END_DATE 
) 
WHERE R = 1 
ORDER BY START_DATE DESC 

Về cơ bản, trước tiên, bộ lọc lọc hàng theo ngày và sau đó bỏ qua tất cả các hàng nhưng đầu tiên là một chia sẻ cùng một MERCHANT_ID.

Xin lưu ý rằng ý nghĩa của "đầu tiên" được xác định tương ứng với thứ tự START_DATE giảm dần. Hai hàng có cùng START_DATE, khi đó "tranh chấp" được giải quyết bằng cách sử dụng thứ tự ID.

+0

Hoàn hảo! Cảm ơn! –

0

Hi một cái gì đó như thế này có thể làm việc:

select id, name,  start_date, end_date from (
select id, name,  start_date, end_date, ROW_NUMBER() 
    OVER (PARTITION BY merchant_id ORDER BY merchant_id) AS rnum from your_table 
    where start_date<=trunc(sysdate) and end_date>=trunc(sysdate)) 
    where rnum=1 
order by start_date desc 

nếu bạn cung cấp một kịch bản thử nghiệm đơn giản để tạo và Populating bảng tôi có thể cung cấp cho bạn truy vấn chính xác.

+0

Tập lệnh thử nghiệm được thêm vào bài đăng gốc. –

0

Tùy thuộc vào loại sql bạn đang chạy (mysql, máy chủ sql, v.v.) sẽ có các câu trả lời thay thế.

Ví dụ, trong sql server bạn có thể nói "Gán mỗi hàng một số, bắt đầu từ 1 cho mỗi thương", và luôn luôn chọn số 1.

Trong sql chung chung, bạn phải có một chút ít trực tiếp . Có vẻ như cột id của bạn được đảm bảo là duy nhất? Nếu có một cách để phân biệt câu hỏi là "có được bản ghi bên trong phạm vi ngày WHERE không có id cao hơn trong cùng một phạm vi ngày cho cùng một người bán"

Bạn có biết cách lọc theo> và < hôm nay không? Tôi nghĩ câu trả lời thế nào để làm điều đó là đặc trưng cho loại sql bạn đang sử dụng:

Vì vậy, hãy thử:

SELECT * from myFavoriteTable 
    WHERE today() < end_date and today > start_date -- for this date criteria use whatever works 
    AND NOT EXISTS (SELECT * from myFavoriteTable as TooLow 
     WHERE today() < end_date and today() > start_date -- as above 
     AND TooLow.Merchant = myFavoriteTable.merchant 
     AND TooLow.id > myFavoriteTable.id) 
+0

SQL là dành cho Oracle. –

-1

Tất cả các câu trả lời khác có vẻ phức tạp hơn ... Bạn có thể sử dụng công cụ sửa đổi DISTINCT trong Oracle để lấy một và chỉ một hàng duy nhất cho mỗi cột cụ thể. Đây là một câu hỏi mà bạn có thể sử dụng để lấy dữ liệu mà bạn muốn, do cấu tạo bảng trong bài viết của bạn:

SELECT DISTINCT merchant_id, id, name, start_date, end_date FROM table WHERE start_date >= today AND end_date < today ORDER BY start_date DESC

+0

Điều này không trả lại kết quả được yêu cầu CHỌN DIỆN TÊN merchant_id, id, name, start_date, end_date TỪ giao dịch WHERE start_date <= trunc (sysdate) VÀ end_date> = trunc (sysdate) ORDER BY start_date DESC; –

+0

Không trả lại các hàng riêng biệt cho một cột đơn – Sasi

Các vấn đề liên quan