2017-06-14 196 views
1

示例表如下:MS SQL:如何在多個用戶的另一個日期(付款日期)之前獲取最新日期(billdate)?

表1

userid | billdate  
user1 | 2017-06-01 
user1 | 2017-05-01 
user1 | 2017-04-01 
user2 | 2017-06-01 
user2 | 2017-05-01 

表2

userid | paymentdate 
user1 | 2017-06-01 
user1 | 2017-06-02 
user1 | 2017-05-02 
user2 | 2017-06-30 
user2 | 2017-05-30 

希望的輸出提前

userid | billdate  | paymentdate 
user1 | 2017-05-01 | 2017-06-01 
user1 | 2017-06-01 | 2017-06-02 
user1 | 2017-05-01 | 2017-05-02 
user2 | 2017-06-01 | 2017-06-30 
user2 | 2017-05-01 | 2017-05-30 

由於

增加了一個場景:如果同一月份有多個付款,該怎麼辦?並且對於每個付款日期,先前的帳單日期應該在期望的輸出中

+0

如果'user1'在'表2'中有三條記錄怎麼辦? –

+0

我認爲您應該將您的付款與帳單關聯起來。如果我沒有收到賬單,我永遠不會付錢給你,因此鏈接應該始終存在。所以基本上你必須在付款表中添加一列「bill_ID」。如果一筆交易支付多筆賬單,這一筆將會有麻煩。您可能需要在前端應用程序 – Luke

+0

上處理該問題。但假設user1只有這些記錄。 –

回答

0

如果你只想返回那裏是一個BillPayment記錄的記錄,那麼我們首先需要作出一些假設 - 即不會有任何兩個Bill付款之間有兩個Payment記錄,或在同一天支付兩筆Bill付款。

假設這一切,你可以使用cross apply獲得最新Payment記錄每個Bill記錄,不返回任何東西在沒有Payment記錄可供選擇:

declare @Bills table(userid nvarchar(10),billdate date); 
insert into @Bills values ('user1','2017-06-01'),('user1','2017-05-01'),('user1','2017-04-01'),('user2','2017-06-01'),('user2','2017-05-01'); 

declare @Payments table(userid nvarchar(10),paymentdate date); 
insert into @Payments values ('user1','2017-06-01'),('user1','2017-06-02'),('user1','2017-05-02'),('user2','2017-06-30'),('user2','2017-05-30'); 

select p.userid 
     ,ba.billdate 
     ,p.paymentdate 
from @Payments p 
    cross apply(select top 1 billdate 
       from @Bills b 
       where p.userid = b.userid 
        and b.billdate < p.paymentdate 
       order by b.billdate desc 
       ) ba 
order by p.userid 
     ,ba.billdate desc 
     ,p.paymentdate desc; 

輸出:

+--------+------------+-------------+ 
| userid | billdate | paymentdate | 
+--------+------------+-------------+ 
| user1 | 2017-06-01 | 2017-06-02 | 
| user1 | 2017-05-01 | 2017-06-01 | 
| user1 | 2017-05-01 | 2017-05-02 | 
| user2 | 2017-06-01 | 2017-06-30 | 
| user2 | 2017-05-01 | 2017-05-30 | 
+--------+------------+-------------+ 
+0

感謝您的詳細回覆。如果在我的現實生活場景中存在多筆付款,那麼該怎麼辦。 :) –

+0

@HopetoChristianChophi正在更新我的答案,就像你正在寫評論:) – iamdave

+2

似乎工作..只是確認與我的活的數據庫...一些活的情況可能已經在示例場景中被忽略...將更新如果我能找到它,或者在確認後將其標記爲答案。請給我一些時間。再次感謝 –

0

您似乎想要加入表格,但沒有密鑰。 row_number()可以提供關鍵:

select t1.*, t2.paymentdate 
from (select t1.*, 
      row_number() over (partition by userid order by billdate) as seqnum 
     from t1 
    ) t1 join 
    (select t2.*, 
      row_number() over (partition by userid order by paymentdate) as seqnum 
     from t2 
    ) t2 
    on t1.userid = t2.userid and t1.seqnum = t2.seqnum; 
-1

你需要從Table01所有行,然後得到的只有一行從TABLE02升序排列。 Table02行通過用戶標識和日期連接(billdate < = paymentdate)。頂部(1)的外部應用將會訣竅。

drop table if exists dbo.Table01; 
drop table if exists dbo.Table02; 

create table dbo.Table01 (
    userid varchar(100) 
    , billdate date 
); 

create table dbo.Table02 (
    userid varchar(100) 
    , paymentdate date 
); 

insert into dbo.Table01 (userid, billdate) 
values ('user1', '2017-06-01'), ('user1', '2017-05-01') 
    , ('user2', '2017-06-01'), ('user2', '2017-05-01'); 

insert into dbo.Table02 (userid, paymentdate) 
values ('user1', '2017-06-02'), ('user1', '2017-05-02') 
    , ('user2', '2017-06-30'), ('user2', '2017-05-30'); 


select 
* 
from dbo.Table01 t1 
    outer apply (
      select 
       top (1) 
       t2.paymentdate 
      from dbo.Table02 t2 
      where t1.userid = t2.userid 
       and t1.billdate <= t2.paymentdate 
      order by t2.paymentdate asc 
    ) tt 
+2

雖然這個腳本看起來像它的實際工作,但代碼只有答案一般不贊成。你需要解釋你在做什麼,爲什麼。 – iamdave

+2

確實,只需將代碼寫入答案將使StackOverflow看起來像它最初不想要的編碼服務。工作代碼很好,但理解它是不可或缺的。 – Luke

+0

@iamdave當然,我編輯了答案。 –

-1

有兩種可能的解決方案:

首先

合併表爲一體。這將使哪些日期屬於哪個賬單和哪個用戶更清楚。因此,所需的輸出是您正在使用的表格。如果用戶已被記帳但尚未付款。付款日期是NULL

添加主鍵到table 1和表2中使用它作爲外鍵,像這樣:

bill_id | userid |s billdate 1 | user1 |s 2017-06-01 2 | user1 |s 2017-05-01 3 | user2 |s 2017-06-01 4 | user2 |s 2017-05-01

表2

bill_id | userid |s paymentdate 1 | user1 |s 2017-06-02 2 | user1 |s 2017-05-02 3 | user2 |s 2017-06-30 4 | user2 |s 2017-05-30

現在你可以輕鬆獲得連接:

SELECT table1.*, table2.paymentdate FROM table1 LEFT JOIN table2 ON table1.bill_id = table2.bill_id;

+0

由於一個賬單可能發生多次交易,第一種解決方案在實踐中將無法正常工作,第二種解決方案几乎是我的評論的複製粘貼,並且由於OP需要提取數據而不是建立新數據,因此沒有解決方案。 – Luke

+0

如果意圖是多次付款,則無法繞過外鍵表。並抱歉複製你。沒有看到您的評論。 – mamazu

+1

只需多次付款,您只需要FK欄。您可以將多個付款行鏈接到一個帳單行。您只需要一張額外的表格即可爲多次付款提供多次付款,這在reallife中是一種可能的情況。 – Luke

相關問題