2013-03-15 5 views
1

Работа со следующим:C# SQL Select Right Таблица в LEFT JOIN возвращает только уникальные значения, а не по одному экземпляру каждого

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(); 
     } 

Теперь это все работает нормально, и денди, если Table2 не имеет несколько значений для 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 первым, чтобы получить элементы с count> 1, а затем добавьте предложение where, чтобы исключить их. Я бы дал вам SQL, но я должен пойти на собрание. – Hogan

+0

, если вы не знакомы с тем, как создать общее выражение таблицы (CTE), вы можете посмотреть этот сайт MSDN [CTE SQL Server] (http://msdn.microsoft.com/en-us/library/ms190766 (v = sql.105) .aspx) – MethodMan

+0

@Hogan Я попробовал это, но был не уверен в sytax, поскольку я добавил любую форму WITH в начало strSelectSql. Я получил исключение SqlException. Я никогда не использовал CTE раньше или раньше, чем функция Count Count (*) = 1. И не может найти много замечательных документов по этому вопросу, особенно при использовании его внутри C#. – user2140261

ответ

3

вместо

LEFT JOIN Table2

попробовать:

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

+0

Это работало точно так, как я ожидал, что это на самом деле почти идентично тому, что у меня было в голове, и попробовал изначально, не уверен, почему мой не работает, но это отлично поработало. Как это сравнивается с тем, что другие пользователи говорят, чтобы попробовать, маршрут CTE, поскольку они кажутся мне почти одинаковыми. – user2140261

+0

Я считаю, что это вопрос предпочтения. Использование CTE должно быть оптимизировано для того же плана. Я предварительно обнаруживаю, что CTE более читабельны, когда подзапросы становятся более сложными, но используют подзапросы для более тривиальных случаев. – paul