2013-03-15 53 views
1

不是一个实例具有以下工作:C#SQL选择右表在左联接仅返回唯一值,每个

string strSelectSql = "SELECT Table1.ID, Table1.Status, 
    Table1.CustomerName,Table1.Date, Table1.LocationID, 
    Table2.LocationID As [LocationID 2] FROM Table1 LEFT JOIN 
    Table2 ON Table1.ID = Table2.ID 
    WHERE (Date Is Null AND ID= @SearchForString AND 
    Status != 'Archived') OR 
    ((Date Between @FromDate AND @ToDate) 
    AND ID= @SearchForString AND Status != 'Archived')"; 

     SqlConnection SqlConn = new SqlConnection(cstrDatabaseConnection); 
     SqlDataAdapter SqlAdpt = new SqlDataAdapter(); 
     SqlCommand SqlCom = new SqlCommand(strSelectSql,SqlConn); 
     SqlCom.Parameters.AddWithValue("@SearchForString",strSearchString); 
     SqlCom.Parameters.AddWithValue("@FromDate",strFromDate); 
     SqlCom.Parameters.AddWithValue("@ToDate",strToDate); 

     SqlAdpt.SelectCommand = SqlCom; 
     try 
     { 
      DataSet TempDS = new DataSet(); 
      SqlConn.Open(); 
      SqlAdpt.Fill(TempDS); 
      SqlConn.Close(); 
      SqlConn.Dispose(); 
      if (Convert.ToInt32(TempDS.Tables[0].Rows.Count) > 0) 
      { 
       dgvQueryResult.DataSource = TempDS.Tables[0]; 
       dgvQueryResult.Refresh(); 
       dgvQueryResult.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); 
       TempDS.Dispose(); 
      } 

     } 
     catch (SqlException sqlE) 
     { 
      MessageBox.Show(sqlE.Message); 
      SqlConn.Close(); 
      SqlConn.Dispose(); 
     } 
     catch (Exception UnknownE) 
     { 
      MessageBox.Show(string.Format("Unknown Exception: {0}",UnknownE.Message); 
      SqlConn.Close(); 
      SqlConn.Dispose(); 
     } 
     finally 
     { 
      if (SqlConn != null) SqlConn.Dispose(); 
     } 

现在,这一切工作正常,很正常,除非表2对LocationID

多个值
Table2 
+----+------------+ 
| ID | LocationID | 
+----+------------+ 
| 1 |  1  | 
| 2 |  2  | 
| 3 |  3  | 
| 4 |  4  | 
| 5 |  5  | 
| 6 |  6  | 
| 6 |  7  | 
| 6 |  7  | 
| 7 |  8  | 
| 7 |  9  | 
+----+------------+ 

我想忽略:

Table2 
+----+------------+ 
| ID | LocationID | 
+----+------------+ 
| 6 |  7  | 
| 6 |  7  | 
+----+------------+ 

,并得到这个:

Table2 
+----+------------+ 
| ID | LocationID | 
+----+------------+ 
| 1 |  1  | 
| 2 |  2  | 
| 3 |  3  | 
| 4 |  4  | 
| 5 |  5  | 
| 6 |  6  | 
| 7 |  8  | 
| 7 |  9  | 
+----+------------+ 

但我想:

Table2 
+----+------------+ 
| ID | LocationID | 
+----+------------+ 
| 6 |  6  | 
+----+------------+ 

因为LocationID不重复。

另外,我想:

Table2 
+----+------------+ 
| ID | LocationID | 
+----+------------+ 
| 7 |  8  | 
| 7 |  9  | 
+----+------------+ 

再次因为LocationID不重复。

如果非要或是否会更有效率我也愿意之前删除从TempDS这些行:

 dgvQueryResult.DataSource = TempDS.Tables[0]; 

如果连必要时,或者最有效的直接从dgvQueryResult

删除条目而不是
+0

首先执行CTE以获取计数大于1的项目,然后将其添加到where子句以排除这些项目。我会给你SQL,但我必须去开会。 – Hogan 2013-03-15 16:14:49

+0

如果您不熟悉如何创建公用表达式(CTE),可以查看此MSDN网站[CTE SQL Server](http://msdn.microsoft.com/zh-cn/library/ms190766(v = sql.105).aspx) – MethodMan 2013-03-15 16:19:50

+0

@Hogan我曾尝试过,但不确定的sytax,因为我在strSelectSql的开头添加了任何形式的WITH我得到了一个SqlException。我以前从来没有使用过CTE或之前有Having Count(*)= 1的函数。而且在这个主题上找不到很多很棒的文档,尤其是在C#中使用它时。 – user2140261 2013-03-15 16:21:29

回答

3

LEFT JOIN Table2

尝试:

LEFT JOIN (Select id, locationId from table2 group by id, locationId having count(*) = 1) as table2

+0

这和我预期的完全一样,这实际上和我脑海中所做的尝试几乎完全相同,不知道为什么我的工作不成功,但是这很好。这与其他用户说什么尝试,CTE路线相比,它们看起来与我差不多。 – user2140261 2013-03-15 16:33:54

+0

我认为这是一个偏好问题。使用CTE应该优化到完全相同的计划。当子查询变得更加复杂时,我会更好地发现CTE更可读,但是使用子查询处理更琐碎的情况。 – paul 2013-03-15 16:38:21