Объединение не работает так, как я ожидаю

#sql #sql-server

#sql #sql-сервер

Вопрос:

У меня есть две таблицы, в которых может быть человек. Я хочу найти их экземпляры в каждой таблице и объединить их вместе. Я надеюсь, что объединение найдет все экземпляры этого человека в обеих таблицах и удалит все избыточные экземпляры. Итак, если бы человек был в таблице A, но не B, он бы появился. Если наоборот, они все равно будут отображаться. Если бы они были на обоих, они бы появились. Но мне нужен только один экземпляр person в результирующем наборе. Прямо сейчас, согласно данным, которые я видел в базе данных, у пользователя есть один экземпляр в обеих таблицах, но в других ситуациях может быть больше. Предполагается, что это возвращает одну строку, а не две, потому что избыточность должна быть удалена, но она ничего не возвращает (0). Ошибок вообще нет, запрос просто неправильный, и я неправильно понимаю объединение и каким-то образом получаю нулевые совпадения.

 SqlCommand getDrivers = new SqlCommand("SELECT DriverPhone FROM Transactions WHERE EstablishmentCode = @ec UNION SELECT PhoneNumber FROM Connection WHERE EstablishmentCode = @ec AND Dispatcher = @disp", myTransactions);
    getDrivers.Parameters.AddWithValue("@ec", "ec");
    getDrivers.Parameters.AddWithValue("@disp", false);
    SqlDataAdapter adapter = new SqlDataAdapter();
    adapter.SelectCommand = getDrivers;
    try
    {
        adapter.Fill(dsDrivers);
        adapter.Dispose();
        getDrivers.Dispose();
        Response.Write(dsDrivers.Tables[0].Rows.Count.ToString());
    }
    catch (Exception err)
    {
        Response.Write("<p>"   err   "</p>");
        //sb.Append("<p style='display:none'>"   err   "</p>");   // shows real error msg for debug but hides it on page
    } 
  

Комментарии:

1. Запрос кажется правильным .. но убедитесь, что столбец имеет тот же тип, а условие where работает правильно.. (может быть, вы неправильно управляете var @ec… или другое)

2. Должен ли параметр @disp также быть строкой?

3. @disp соответствует столбцу bool / bit, поэтому я подумал, что ввод false будет правильным. Не уверен. Должно ли оно быть 0 или 1? Это sql server, а не мой sql

4. оба набора столбцов имеют один и тот же тип данных, однако во второй части запроса есть дополнительный фильтр

5. Я думаю, что для false оно должно быть 0.

Ответ №1:

Если вам нужны отдельные строки, которые находятся в обоих наборах, то вам нужно что-то вроде intersect not union . Например:

 SELECT DriverPhone
FROM Transactions
WHERE EstablishmentCode = @ec 
INTERSECT
SELECT PhoneNumber 
FROM Connection
WHERE EstablishmentCode = @ec AND Dispatcher = @disp;
  

Вы можете прочитать об INTERSECT этом в документации.

Если ваша база данных не поддерживает intersect , просто используйте условную логику:

 SELECT DISTINCT DriverPhone
FROM Transactions
WHERE EstablishmentCode = @ec AND
      DriverPhone IN (SELECT c.PhoneNumber 
                      FROM Connection c
                      WHERE c.EstablishmentCode = @ec AND c.Dispatcher = @disp
                     );
  

Примечание: это используется SELECT DISTINCT в случае Transactions , если для данного есть повторяющиеся записи DriverPhone . Использование UNION в вопросе предполагает, что вы хотите удалить дубликаты.

Ответ №2:

getDrivers.Parameters.AddWithValue(«@ec», «ec»);

«ec» должен был ссылаться на строковую переменную val, установленную ранее, поэтому у нее не должно было быть кавычек.