SQL命令WHERE可以在同一命令行中使用,但可以在2个不同的表上使用

时间:2012-06-22 18:39:26

标签: sql sql-server sql-server-2008

我有两张桌子要加入。

表1

Year, ID, Theme,

表2

First, Last, WeekID, Date, Affiliation

我想使用此命令

SELECT * 
FROM Table1 
CROSS JOIN Table2 
WHERE Table1.ID = 5 
    AND WHERE Table2.Date >= 1/1/2011 
    AND Table2.Date <= 12/30/2011 
ORDER BY Asc

我想要发生的是选择表1中的所有行和列,其中ID列包含int值5.在表2中,应选择在给定日期范围内的所有列和行。 / p>

我想知道WHERE子句是否应该在CROSS JOIN子句之后,如上所述。我还应该删除第二个WHERE关键字,而是使用以下命令。

SELECT * 
FROM Table1 
CROSS JOIN Table2 
WHERE Table1.ID = 5 
    AND Table2.Date >= 1/1/2011 
    AND Table2.Date <= 12/30/2011 
ORDER BY Asc

我的第三个问题是棘手的问题。可以在这样的单个命令中使用2个不同的WHERE子句,但是可以应用于单独的表吗?我加入桌子时可以WHERE Table1 (*Condition*) AND WHERE Table2 (*Condition*)的意思吗?

我认为我可以通过为每个表创建2个单独的SQL命令1来轻松解决整个问题,并避免使用JOIN2 WHERE子句。这会是你推荐的吗?

最终结果看起来像这样

表3

ID, Year, Theme, WeekID, Date, First, Last, Affiliation

然后,细胞将根据日期按升序排序。

下面有一个样本表

表3

ID     Year     Theme     WeekID     Date          First      Last    Affiliation
5      2011     Stuff1    1          01/09/2011    Foo        Bar     Baz Inc
5      2011     Stuff2    2          01/14/2011    Flum       Baz     Bar Inc
5      2011     Stuff3    3          04/15/2011    Bar        Flum    Bub Inc
5      2011     Stuff4    4          05/01/2011    Bar        Foo     FlumBub Inc 
5      2011     Stuff5    5          08/16/2011    Bub        Baz     Foo Inc 

3 个答案:

答案 0 :(得分:1)

问:我想知道WHERE子句是否应该出现在我上面的CROSS JOIN子句之后。

答:是的,这是WHERE子句的正确位置。

问:我是否应该删除第二个WHERE关键字,而是使用以下命令。

答:是的,WHERE子句只能在简单的SELECT语句中出现一次。每个子查询都有自己的WHERE子句,但每个SELECT实际上仍然只有一个WHERE子句。

问:我的第三个问题是棘手的问题。可以在这样的单个命令中使用2个不同的WHERE子句,但是可以应用于单独的表吗?当我加入表时,我可以使用WHERE Table1(条件)和WHERE Table2(条件)吗?

答: WHERE关键字每SELECT只能出现一次。您可以在任何表格中包含谓词。


另外,要回答一些您没有问过的其他问题......

您需要在ORDER BY子句中提供表达式或表达式列表。默认顺序为ASC,因此最常省略此关键字。

Table2的Date列上的谓词似乎表示日期文字。 (正如它们在你的陈述中,它们似乎代表一个整数值,由一系列除法运算得出。

应该将文字显式转换为DATETIME(以匹配Date列的数据类型)。 SQL Server不需要显式的CONVERT,但如果没有转换,您确实希望这些转换为规范(明确)格式的字符串。 ('3/5/2012'代表3月5日,还是5月3日?)

SQL Server DATTIME数据类型存储日期和时间组件。通常,当用户要求结束日期时,它们也意味着当天的任何时间。考虑到'2011-12-30 09:30:00'的DATETIME值不是&lt; ='2011-12-30',我们通常会编写一个小于第二天午夜的测试。< / p>

将列引用限定为非常好的做法。这通常使用表别名来完成。表别名不是必需的,但它们是熟悉的模式,可以使读取语句更容易。当表名完全限定mydatabase.schema.MyLongAndUnWeILDyTblName时,尤其如此,并且在更复杂的表达式中使用的完全限定列名称可能会使表达式解密变得非常繁琐。 (在你的情况下,这不是一个问题,但它是我们遵循的简单陈述的模式。)

此外,最佳做法是避免在SELECT列表中使用*(除非您从语句中的内联视图或CTE中进行选择)。而是列出要返回的特定表达式。对于测试和开发,使用*是好的。除了这些小问题,你的陈述看起来还不错。

(避免使用*和符合条件的列名可以避免将来发生的问题,例如,当一个新列添加到表中时,会产生一个之前没有的“模糊列”异常。(我们希望能够在不对应用程序中的每个SQL语句运行完整回归测试的情况下添加列。)

鉴于您在我们的商店中没有要求的所有信息,返回指定结果集的语句将格式如下:

SELECT t1.ID
     , t1.Year
     , t1.Theme
     , t2.WeekID
     , t2.Date
     , t2.First
     , t2.Last
     , t2.Affiliation
  FROM dbo.Table1 t1
 CROSS
  JOIN dbo.Table2 t2
 WHERE t1.ID = 5 
   AND t2.Date >= CONVERT(DATETIME,'2011-01-01',20)
   AND t2.Date <  CONVERT(DATETIME,'2011-12-31',20)
 ORDER
    BY t1.ID
     , t1.Year
     , t1.Theme
     , t2.WeekID
     , t2.Date
     , t2.First
     , t2.Last
     , t2.Affiliation

在后来的评论中,Derek指出Date列是VARCHAR。在那个不幸的情况下,我们需要知道日期的格式。

如果字符串表示形式不是规范格式,则VARCHAR比较将产生不良结果。

(注意到字符串'3/5/2011'不在'2011年1月1日'和'12 / 30/2011'之间。)

使用DATETIME数据类型存储日期值有很多好处。如果那是不可能的(因为有人提出任何不正确的原因),并且字符串不是规范格式,那么谓词应该更像是:

AND CONVERT(DATETIME,t2.Date,101) >= CONVERT(DATETIME,'01/01/2011',101)
AND CONVERT(DATETIME,t2.Date,101) <  CONVERT(DATETIME,'12/31/2011',101)

答案 1 :(得分:0)

我认为你最好使用这样的CTE:

WITH Table1CTE (COL1, COL2)
AS
(
SELECT COL1, COL2
FROM Table1 
WHERE Table1.ID = 5
),
Table2CTE (COL3, COL4)
AS
(
SELECT COL3, COL4
FROM TABLE2
WHERE Table2.Date >= 1/1/2011 
    AND Table2.Date <= 12/30/2011
)
SELECT *
FROM Table1CTE CROSS JOIN Table2CTE
ORDER BY COL1 ASC

答案 2 :(得分:0)

第一个SELECT命令

SELECT *  
FROM Table1  
CROSS JOIN Table2  
WHERE Table1.ID = 5  
    AND WHERE Table2.Date >= 1/1/2011  
    AND Table2.Date <= 12/30/2011  
ORDER BY Asc 

会产生

  

关键字WHERE

附近的语法错误不正确

只需要使用一个WHERE语句,AND可以指定任何其他条件。

此外,上述日期需要格式化为

Table2.Date >= '01/01/2011'  AND Table2.Date <= '12/30/2011'

否则,SQL命令将执行整数运算并将类型转换为int,而不是将日期字符串与表格中varchar类型的日期匹配。