Oracle

如何查詢oracle 10中每個組的最後插入行

  • May 1, 2020

我有兩個關於使用者的表格,我想加入兩個表格並顯示每個使用者的最新評論

下面是表格

在此處輸入圖像描述

我想查詢每個使用者的最新評論(每個使用者 1 條評論)波紋管我寫的查詢但是如果日期和時間相同,它會返回每個使用者的多個評論

SELECT a.cust_id,b.remarks,b.contact_date,b.contact_time FROM customers a,(select * from customer_review
where (cust_id,contact_time,contact_date) in (select cust_id, max(contact_time),max(contact_date) from customer_review group by cust_id)
) b WHERE  a.cust_id=b.cust_id;

在此處輸入圖像描述

請為每個使用者查詢 1 條評論提供任何解決方案(注意:抱歉,如果有的話,我無法更改列詳細資訊) 實時連結Oracle Live

你想要做的是這樣的事情,使用 ROW_NUMBER() 和PARTITIONcust_id 和ORDERing BY contact_time DESC,這樣第一個將是最新的。這裡有一個小提琴- Oracle 具有微秒精度,因此您不太可能同時remarks被同一客戶同時獲得。

創建並填充客戶表:

CREATE TABLE customers
(
 cust_id INTEGER NOT NULL,
 cust_name VARCHAR (25) NOT NULL
);

INSERT INTO customers VALUES (1234, 'John Doe');
INSERT INTO customers VALUES (1235, 'Ram'); 
INSERT INTO customers VALUES (1236, 'Rahim');

對 customer_review 執行相同的操作:

CREATE TABLE customer_review
(
 review_id VARCHAR (25) NOT NULL,
 cust_id   INTEGER NOT NULL,
 remarks   VARCHAR (250) NOT NULL,
 contact_date DATE NOT NULL,
 contact_time TIMESTAMP NOT NULL
);

INSERT INTO customer_review VALUES 
('NEW123', 1235, 'I am new user', 
TO_DATE('2019-10-27', 'yyyy-mm-dd'), TO_TIMESTAMP('2019-10-27 06:10:13.278',  'yyyy-mm-dd hh24:mi:ss:ms'));
INSERT INTO customer_review VALUES 
('CUST123', 1234, 'This is awesome product', 
TO_DATE('2019-10-26', 'yyyy-mm-dd'), TO_TIMESTAMP('2019-10-26 11:15:15.123', 'yyyy-mm-dd hh24:mi:ss:ms'));
INSERT INTO customer_review VALUES 
('CUST124', 1234, 'This is not good product. I have changed my mind now', 
TO_DATE('2019-10-27', 'yyyy-mm-dd'), TO_TIMESTAMP('2019-10-27 16:25:15.567', 'yyyy-mm-dd hh24:mi:ss:ms'));
INSERT INTO customer_review VALUES 
('CUST125', 1234, 'After upgrade, it is now working fine!', 
TO_DATE('2019-10-27', 'yyyy-mm-dd'), TO_TIMESTAMP('2019-10-27 19:52:56.345', 'yyyy-mm-dd hh24:mi:ss:ms'));

然後執行以下 SQL:

SELECT c.cust_name, t.cust_id, t.remarks FROM
(
 SELECT 
   ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY cust_id ASC, contact_time DESC) AS rn, 
   *
 FROM customer_review
) t
JOIN customers c
 ON t.cust_id = c.cust_id
WHERE t.rn = 1;

結果:

CUST_ID     REMARKS                                  CUST_NAME
  1234     After upgrade, it is now working fine!   John Doe
  1235     I am new user                            Ram

(編輯後 - 這些現在是正確答案 - John Doe 的評論應該是他的最新評論!Ram 只發表了一條評論,因此根據定義,它是最新的)。

幾句忠告。您的客戶表是複數形式,customer_review 是單數形式 - 選擇其中一個並堅持使用(您可以搜尋“SQL 樣式指南”並選擇您喜歡的一個。就個人而言,我推薦單數 - 表是一組事物的,因此是單一的。

下次發帖時,能否將您的表格定義包含為 DDL 文本 ( CREATE TABLE xxxx (field_1 type_1...);) 並將您的數據包含為 DML 文本 ( INSERT INTO xxxx VALUES (val_1, val2...);)。以下是為什麼發布螢幕截圖不是解決 DBA.SE 問題的最佳方法的幾個原因。在我的個人資料中有幾篇關於如何提問的文章 - 你可能想看看?

最後,我建議您使用整數review_id- 它使排序更容易 - 否則您可能會面臨不得不使用諸如

SELECT CAST(SUBSTR('CUST1235',  5, LENGTH('CUST1235')) AS SMALLINT) AS no;

INTEGERreview_id欄位中提取。

可以使用 Oracle ROWNUM偽列解決此問題,但這是非標準的,最好養成良好的習慣 - 如果您/您的公司決定這樣做,它將使您的應用程序更具可移植性。我希望這有幫助 - 如果它不符合您的要求,請告訴我,我們可以嘗試修改它。ps 歡迎來到論壇!:-)

編輯:

我終於讓 Oracle 小提琴在這里工作了——精確到微秒。

在重讀問題和我的答案時讓我印象深刻的另一點。您不需要聲明一個contact_date欄位 - 它可以很容易地從 contact_time 欄位派生出來。因此,數據(在這種情況下為日期)僅儲存在一個欄位和一個欄位中 - 這符合 RDBMS 最佳實踐。

有兩種方法可以做到這一點

  • 呼叫表時可以使用 TO_DATE 函式。您的表格現在看起來像這樣(註釋contact_date已被註釋掉。然後您只需TO_DATE(contact_time)在您只想獲取日期時呼叫(範例在小提琴 - 表格中顯示customer_review_bis)。

CREATE TABLE customer_review_bis
(
 review_id VARCHAR (25) NOT NULL,
 cust_id   INTEGER NOT NULL,
 remarks   VARCHAR (250) NOT NULL,
 -- contact_date DATE NOT NULL,
 contact_time TIMESTAMP NOT NULL
);
  • 您還可以使用GENERATED AS(aka COMPUTED BYor CALCULATED) 列。這些非常方便,一旦定義,您就可以有效保證日期將始終與contact_time. 此功能曾經由TRIGGERs 執行 - 確實值得學習這些功能。這裡column_name [datatype] [GENERATED ALWAYS] AS (expression) [VIRTUAL]描述了語法(oracle-base 是一個超級站點)。您的表定義現在變為(也顯示在 fiddle - 中): customer_review_ter

CREATE TABLE customer_review_ter
(
 review_id VARCHAR (25) NOT NULL,
 cust_id   INTEGER NOT NULL,
 remarks   VARCHAR (250) NOT NULL,
 contact_time TIMESTAMP NOT NULL,
 contact_date DATE GENERATED ALWAYS AS (TO_DATE(contact_time)) VIRTUAL
);  -- you just treat contact_date as a normal field when you call it, in 
   -- exactly the same way as you did in your original example - table 
   -- customer_review (first one) in the fiddle.

如果選擇GENERATED AS,則必須通過添加可更新的欄位來稍微修改INSERT語句:

INSERT INTO customer_review_ter 
(review_id, cust_id, remarks, contact_time)
VALUES (.... data for specified fields ....);

最後,正如@EdStevens 所說,Oracle 10 是 EOL(生命終結)——你真的應該考慮升級!

引用自:https://dba.stackexchange.com/questions/252488