我有一個顧客產品訂購資料表A簡單表示如下
c_no year mon num
c001 2020 12 50
c001 2021 1 100
c001 2021 3 50
c002 2021 1 70
c002 2021 3 50
c002 2021 4 90
c002 2021 7 100
另一個訂購規格表B簡單表示如下
c_no year mon color size
c001 2021 1 red M
c002 2021 2 blue S
c002 2021 4 yellow XL
我想將上面兩個表格合併如下
c_no year mon num color size
c001 2020 12 50 red M
c001 2021 1 100 red M
c001 2021 3 50 red M
c002 2021 1 70 blue S
c002 2021 3 50 blue S
c002 2021 4 90 yellow XL
c002 2021 7 100 yellow XL
也就是說
訂購規格表(表B)與產品訂購表(表A)的時間上並非重合。
在訂購規格登錄(表B)的時間點之前及之後所有的訂單(表A)的產品規格需參照該登錄的規格計算,直至下一次訂購規格登錄才改為新的規格。
請問我要如何使用SQL指令,以表A為基礎join表B的資料呢?
@@".....用慣用SQL
declare @data table(
c_no varchar(50)
,years int
,mon int
,num int
)
declare @head table(
c_no varchar(50)
,years int
,mon int
,color varchar(50)
,size varchar(50)
)
insert into @data
values('c001',2020,12,50)
,('c001',2021,1,100)
,('c001',2021,3,50)
,('c002',2021,1,70)
,('c002',2021,3,50)
,('c002',2021,4,90)
,('c002',2021,5,100)
insert into @head
values('c001',2021,1,'red','M')
,('c002',2021,2,'blue','S')
,('c002',2021,4,'yellow','XL')
select a.*
,isNull((
select top 1 color
from @head c
where a.c_no = c.c_no
and Convert(varchar,a.years) + '/' + Convert(varchar,a.mon) + '/1'
>= Convert(varchar,c.years) + '/' + Convert(varchar,c.mon) + '/1'
order by c.years,c.mon desc
),(
select top 1 color
from @head c
where a.c_no = c.c_no
and Convert(varchar,a.years) + '/' + Convert(varchar,a.mon) + '/1'
< Convert(varchar,c.years) + '/' + Convert(varchar,c.mon) + '/1'
order by c.years,c.mon
)) color
,isNull((
select top 1 size
from @head c
where a.c_no = c.c_no
and Convert(varchar,a.years) + '/' + Convert(varchar,a.mon) + '/1'
>= Convert(varchar,c.years) + '/' + Convert(varchar,c.mon) + '/1'
order by c.years,c.mon desc
),(
select top 1 size
from @head c
where a.c_no = c.c_no
and Convert(varchar,a.years) + '/' + Convert(varchar,a.mon) + '/1'
< Convert(varchar,c.years) + '/' + Convert(varchar,c.mon) + '/1'
order by c.years,c.mon
)) size
from @data a
CREATE TABLE #TABLE_A (
c_no VARCHAR(20)
,[year] VARCHAR(20)
,mon VARCHAR(20)
,num VARCHAR(20)
)
CREATE TABLE #TABLE_B (
c_no VARCHAR(20)
,[year] VARCHAR(20)
,mon VARCHAR(20)
,color VARCHAR(20)
,size VARCHAR(20)
)
INSERT INTO #TABLE_A (c_no,[year],mon,num)Values('c001','2020','12','50')
INSERT INTO #TABLE_A (c_no,[year],mon,num)Values('c001','2021','1','100')
INSERT INTO #TABLE_A (c_no,[year],mon,num)Values('c001','2021','3','50')
INSERT INTO #TABLE_A (c_no,[year],mon,num)Values('c002','2021','1','70')
INSERT INTO #TABLE_A (c_no,[year],mon,num)Values('c002','2021','3','50')
INSERT INTO #TABLE_A (c_no,[year],mon,num)Values('c002','2021','4','90')
INSERT INTO #TABLE_A (c_no,[year],mon,num)Values('c002','2021','7','100')
INSERT INTO #TABLE_B (c_no,[year],mon,color,size)Values('c001','2021','1','red','M')
INSERT INTO #TABLE_B (c_no,[year],mon,color,size)Values('c002','2021','2','blue','S')
INSERT INTO #TABLE_B (c_no,[year],mon,color,size)Values('c002','2021','4','yellow','XL')
SELECT
#TABLE_A.c_no
,#TABLE_A.[year]
,#TABLE_A.[mon]
,#TABLE_A.num
,#TABLE_B.color
,#TABLE_B.size
FROM #TABLE_A
LEFT JOIN #TABLE_B
ON #TABLE_A.c_no = #TABLE_B.c_no
DROP TABLE #TABLE_A
DROP TABLE #TABLE_B
是這樣嗎?
我看完之後,猜測需求如下
小弟我資歷尚淺,感覺這需求比較複雜,單純靠Query沒有辦法處理,覺得寫一個function輔助輸出資料比較實際一點。
另外,為了符合這筆資料(c002 2021 4 90 yellow XL)的結果,呼叫function我是用2號帶進去的。
create or alter function fn_ttt(@cno varchar(10), @the_date date)
returns @result table(color varchar(10), size varchar(10))
as
begin
declare @temp table(ID int, c_no varchar(10), [year] int, mon int, color varchar(10), size varchar(10))
insert into @temp(ID, c_no, [year], mon, color, size)
select ROW_NUMBER() over(order by [year], mon) as ID, T.*
from (values
('c001', 2021, 1, 'red', 'M'),
('c002', 2021, 2, 'blue', 'S'),
('c002', 2021, 4, 'yellow', 'XL')
) T(c_no, [year], mon, color, size)
declare @id int = (
select T1.ID from @temp T1 inner join @temp T2 on T1.c_no = T2.c_no and T1.ID = T2.ID-1
where T1.c_no = @cno and @the_date
between convert(date, CONCAT(T1.[year], '/', T1.mon, '/01'))
and convert(date, CONCAT(T2.[year], '/', T2.mon, '/01'))
)
if @id is null begin
if not exists(select 1 from @temp where c_no = @cno and @the_date < convert(date, CONCAT([year], '/', mon, '/01')))
set @id = (select max(ID) from @temp where c_no = @cno)
else if not exists(select 1 from @temp where c_no = @cno and @the_date > convert(date, CONCAT([year], '/', mon, '/01')))
set @id = (select min(ID) from @temp where c_no = @cno)
end
insert into @result(color, size)
select color, size
from @temp
where ID = @id
return;
end
go
select row_number() over(order by T.c_no) as ID,* into #aa
from (
values
('c001', 2020, 12, 50)
('c001', 2021, 1, 100)
('c001', 2021, 3, 50),
('c002', 2021, 1, 70),
('c002', 2021, 3, 50),
('c002', 2021, 4, 90),
('c002', 2021, 7, 100)
) T(c_no,[year],mon,num)
select A.c_no, A.[year], A.mon, A.num, F.color, F.size
from #aa A cross apply fn_ttt(A.c_no, convert(date, CONCAT(A.[year], '/', A.mon, '/02'))) F