2013-07-16 50 views
0

我有一個表舉辦活動和日期:如何將一個SQL表中的日期與另一個表中定義的範圍進行比較?

NAME | DOB 
------------------- 
Adam | 6/26/1999 
Barry | 7/18/2005 
Daniel| 1/18/1984 

我有另一個表定義的日期範圍爲開始或結束時間,每一個描述性的代碼:

CODE  | DATE 
--------------------- 
YearStart| 6/28/2013 
YearEnd | 8/14/2013 

我想寫SQL將查找所有在第二個表中描述的時間的開始和結束之間的生日。 YearStart將始終在六月,而YearEnd將始終在八月。我的想法是嘗試:

SELECT 
     u.Name 
     CAST(MONTH(u.DOB) AS varchar) + '/' + CAST(DAY(u.DOB) AS varchar) as 'Birthdate', 
     u.DOB as 'Birthday' 
FROM 
     Users u 
WHERE 
     MONTH(DOB) = '7' OR 
     (MONTH(DOB) = '6' AND DAY(DOB) >= DAY(SELECT d.Date FROM Dates d WHERE d.Code='YearStart')) OR 
     (MONTH(DOB) = '8' AND DAY(DOB) <= DAY(SELECT d.Date FROM Dates d WHERE d.Code='YearEnd'))) 
ORDER BY 
     MONTH(DOB) ASC, DAY(DOB) ASC 

但這並不通,我猜是因爲沒有保證內部SELECT語句將返回只有一行,所以不能被解析爲日期。我怎樣才能真正完成這個查詢?

+0

「DOB」和「DATE」字段的數據類型是什麼? –

+0

我建議您將'YearStart'和'YearEnd'更改爲'Columns'而不是'Rows' – EmmanuelRC

+0

如果您的第二個表中可能有多行返回,您如何區分範圍? –

回答

2

這似乎很奇怪,我仍然覺得我們錯過了相關的一部分要求,但請看以下內容。從你的描述看來,這些年份是無關緊要的,你想要的是在給定月份/日期之間的生日。

SELECT 
    t1.Name, t1.DOB 
FROM 
    t1 
    JOIN t2 AS startDate ON (startDate.Code = 'YearStart') 
    JOIN t2 AS endDate ON (endDate.Code = 'YearEnd') 
WHERE 
    STUFF(CONVERT(varchar, t1.DOB, 112), 1, 4, '') BETWEEN 
     STUFF(CONVERT(varchar, startDate.[Date], 112), 1, 4, '') 
     AND 
     STUFF(CONVERT(varchar, endDate.[Date], 112), 1, 4, '') 
+0

這就是我需要的。 WHERE子句是有道理的,我只是很好奇,如果有人能夠解釋FROM子句的行爲如何在純英文中起作用。 – FunkyDelPueblo

+1

它連接第二個表格兩次。然後它給出兩個連接表的別名「startDate」和「endDate」 您通常會看到來自正在連接的兩個表中的每個連接的JOIN引用列的「ON」部分... JOIN t2 ON(t1 .Id = t2.Id) ...但在這種情況下,我們通過在代碼列中查找所需值來限制記錄。 – dazedandconfused

+0

謝謝,現在完美。 – FunkyDelPueblo

0

嘗試使用一個PIVOT來獲得同一行的年份,就像這樣。這將只返回'Bob'

DECLARE @Names TABLE(
NAME VARCHAR(20), 
DOB VARCHAR(10)); 

DECLARE @Dates TABLE(
CODE VARCHAR(20), 
THEDATE VARCHAR(10)); 

INSERT @Names (NAME,DOB) VALUES ('Adam', '6/26/1999'); 
INSERT @Names (NAME,DOB) VALUES ('Daniel', '1/18/1984'); 
INSERT @Names (NAME,DOB) VALUES ('Bob', '7/1/2013'); 

INSERT @Dates (CODE,THEDATE) VALUES ('YearStart', '6/28/2013'); 
INSERT @Dates (CODE,THEDATE) VALUES ('YearEnd', '8/14/2013'); 

SELECT * FROM @Names; 
SELECT * FROM @Dates; 

SELECT n.* 
FROM @Names AS n 
INNER JOIN (
    SELECT 
      1 AS YearTypeId 
      , [YearStart] 
      , [YearEnd]  
    FROM (SELECT [CODE] 
         , THEDATE 
       FROM  @Dates 
      ) p PIVOT (MIN(THEDATE) 
         FOR [CODE] 
          IN ([YearStart],[YearEnd]) 
        ) AS pvt) AS y 
ON 
    n.DOB >= y.YearStart 
    AND n.DOB <= y.YearEnd  
0

從你問題的最後一段,我假設日期表每年有一個YearStart和一個YearEnd行,對嗎?如果是這樣,那麼你的SQL查詢應該包括你感興趣的年份。

此外,即使「日期」不嚴格地說是SQL Server的保留字(請參閱Reserved Keywords for Transact SQL),您應該避免使用這樣的列名,例如,ODBC不允許它們。

但是,如果僅僅使用您已經提供的信息做某件事,那麼您可以這樣做來獲得日期中定義的最後一年的生日慶祝者(如果該年份的年份開始和年終結果都是真實的):

SELECT DISTINCT <the rest as in your example> 
FROM Users u 
WHERE u.DOB >= (SELECT max(d1.Date) FROM Dates d1 WHERE d1.Code = 'YearStart') 
    AND u.DOB <= (SELECT max(d2.Date) FROM Dates d2 WHERE d2.Code = 'YearEnd') 
ORDER BY u.DOB; 

上面的查詢(我沒有測試之間的主要區別 - 這是隻是爲了顯示原理)和你的帖子是取它的變種,你有,我相信時間類型(或用於數據庫中)按預期工作。我的意思是數據庫引擎很清楚(它的應該是),其中兩個完整日期中的哪一個是最早和最晚的 - 你不必分別提取和比較它們的組件。

/Bosse

相關問題