2012-10-15 57 views
2

說,我有Ç列和Ñ行的表。我想生成一個select語句,表示該表的「加入」,數據範圍包括012天,結果集應該有C + 1列(最後一個是日期)和NXM行。SQL JOIN表具有日期範圍

簡單的例子,以澄清事情: 鑑於見下表一個

select * from A; 
avalue | 
--------+ 
"a"  | 

而且從10至2012年10月12日期範圍,我想下面的結果集:

avalue | date 
--------+------- 
"a"  | 2012-10-10 
"a"  | 2012-10-11 
"a"  | 2012-10-12 

(這是我需要的最終計算任何給定日期的庫存水平的墊腳石,給定起始值和增量)

+0

您使用** C **,** N **和** M **讓我頭暈。你是否要求動態查詢? – Kermit

+0

你正在使用哪種RDBMS? – amphibient

+1

但無論RDBMS,我建議有一個日曆表(如果您的商業模式需要,您也可以用於工作日管理)和簡單的笛卡爾產品日曆表到表A – amphibient

回答

6

PostgreSQL的辦法做到這一點很簡單:

SELECT t.*, g.day 
FROM tbl t 
CROSS JOIN generate_series('2012-10-10'::date 
          , '2012-10-12'::date 
          , '1 day') g(day); 

正好產生的輸出要求。要點是:

  • 功能generate_series()(如@mu已經評論)
    在這種情況下的變體爲date/timestamp
  • A CROSS JOIN - 非常基本的無條件連接。

同樣的,更簡潔:

SELECT * 
FROM tbl t 
    , generate_series('2012-10-10'::date, '2012-10-12'::date, '1 day') day 

對於任意日期,你可以使用一個子選擇或CTE與VALUES表達。沒有必要堅持這樣一個表:

SELECT * 
FROM tbl t 
CROSS JOIN (
    VALUES 
    ('2012-08-13'::date) 
    ,('2012-09-05') 
    ,('2012-10-10') 
    ) g(day); 
2

如果日期表中有更多的日期比你有興趣,然後做

select a.avalue, b.date from a, b where b.date between '2012-10-10' and '2012-10-12' 

其他明智的,如果日期表只包含您感興趣的日期,笛卡爾加入會做到這一點:

select * from a,b; 
+0

其實我試圖避免不得不定義一個日期表,如果可能的話。沒有特別的原因,知識分子好奇。 –

1
declare 
    @Date1 datetime = '20121010', 
    @Date2 datetime = '20121012'; 

with Dates 
as 
(
    select @Date1 as [Date] 
    union all 
    select dateadd(dd, 1, D.[Date]) as [Date] 
    from Dates as D 
    where D.[Date] <= DATEADD(dd, -1, @Date2) 
) 
select 
    A.value, D.[Date] 
from Dates as D 
    cross join A 
0

我不是你的M表中的很清楚。假如你有這樣一個有日期的表格(M),在交叉連接之後會帶來結果。

SELECT C.*, M.date FROM C CROSS JOIN M 
+0

我想避免使用數據表。如果可能的話,我想加入一個缺乏表格表示的「數據範圍」。 –

1

對於MySQL

架構/數據:

CREATE TABLE someTable 
(
    someCol varchar(8) not null 
); 

INSERT INTO someTable VALUES ('a'); 

CREATE TABLE calendar 
(
    calDate datetime not null, 
    isBus bit 
); 

ALTER TABLE calendar 
ADD CONSTRAINT PK_calendar 
PRIMARY KEY (calDate); 

INSERT INTO calendar VALUES ('2012-10-10', 1); 
INSERT INTO calendar VALUES ('2012-10-11', 1); 
INSERT INTO calendar VALUES ('2012-10-12', 1); 

查詢:

select s.someCol, c.calDate from someTable s, calendar c; 
1

你真的有什麼你正在嘗試做的兩個選項。

  1. 如果您的RDBMS支持它(我知道SQL Server會,但我不知道任何其他人),您可以創建一個table-valued function這需要在一個日期範圍,並返回結果集所有離散日期在該範圍內。你會做你的表和函數之間的笛卡爾連接。

  2. 您可以創建一個日期值的靜態表,然後在兩個表之間進行笛卡爾連接。

第二個方案將有更好的表現,特別是如果你正在處理大日期範圍,然而,該解決方案將無法處理任意日期範圍。但是,那麼你應該知道你的最低日期,並且隨着時間的推移,你可以一直添加更多的日期到你的桌子上。