Есть таблица событий:
Иванов Вход
Петров Вход
Сидоров Выход
Иванов Выход
К нему подсоединена таблица контактов
Когда я вывожу на отдельный DataGridView только поле имени контакта, получаю
Иванов
Иванов
Петров
Сидоров
Т.е. данные дублируются, если одни и тот же человек занесен несколько раз в таблицу событий с разными данными. Это правильно, но каким образом можно убрать это дублирование и в DataGridView вывести просто список контактов?
Нравится
DataGridView отвечает за отображение данных, полученных в выборке, вам следует доработать логику SelectQuery . Для исключения повторений вы можете воспользоваться свойством Distinct (исключать дубли) в SQ или использовать Group By
Но вообще говоря вам следует переработать логику SQ, так что бы вы получали данные без дублей.
Свойство исключение дублей пробовала, не помогло.
Дело в том, что данные из таблицы контактов должны повторяться в этой табл. Ведь, если Иванов за один день совершил несколько событий, про это есть несколько записей.
Возможно ли создать фильтр по умолчанию, который я б применила к DataGridView, который б убирал фильтры из списка контактов?
Елена, предлагаю вам создать представление в DataGridView, в котором включать и выключать соответствующие фильтры. Прошу ознакомится с инструкцией Создать представление.doc
Можете воспользоваться фильтром типа Exists
Что-то вроде этого:
select * from tbl_contact c where exists (select e.id from tbl_events e where e.contactid = c.id)
Алексей, я наверное, не корректно поставила вопрос. Как делать фильтр по умолчанию я знаю, у меня вопрос в самой логике фильтра. Как создать фильтр который будет исключать дубли?
Андрей, если я правильно поняла Ваш пример, такой фильтр выведет контакты которые есть в табл событий, а мне же нужно простой список всех контактов, даже которых нет в событиях, но при этом без дублей.
В ContactName содержаться имена контактов, которые мне надо вывести. P_FAM - имена из таблицы событий, которая присоединена к контактам
Можете использовать подзапрос для получения колонки с именами из таблицы событий. Примерно такой вид (свои только данные подставите):
создала:
SubSelectColumn
Select (выбирать первые: 1)
Name
From tbl_Contact
Выдало 1 контакт и все.
Поставила вместо единицы -1, вообще ничего не показывает
"Кошкаров Андрей" написал:подзапрос для получения колонки с именами из таблицы событий.
В таблице событий имена не всех контактов, а только тех, кто совершил событие, а мне нужен полный список контактов, который находится в колонке ContactName, но если я просто вывожу в представлении это поле, имена повторяются столько раз, сколько были задействованы в событиях
Выложите пример вашего запроса, думаю вы что-то упустили.
Появилась другая идея. Вот есть в DataGridView этот список контактов. Возможно ли сделать так чтобы он был недоступен по умолчанию, но при использовании определенного фильтра, отфильтрованный список появлялся? Если да, то подскажите на какое событие
Елена, Вам нужно, чтобы при переходе на представление выполнялся запрос:
select distinct ContactName from Contact
Важно, чтобы была одна колонка, чтобы не было дублей. Но поскольку при переходе на представление автоматически включается только фильтр, указанный в дизайнере, то дистинкт Вам нужно включать самой, т.к. по умолчанию не нужно, чтобы он был включен в sq_Сontact. Нужно найти событие переключения представлений в реестре или что-то подобное, если есть, и если происходит выбор этого представления включать дистинкт. И еще раз повторю, что в представлении должна быть одна колонка.
попробовала создать SQL-фильтр с текстом:
SELECT DISTINCT Name FROM tbl_Contact
и применить его по умолчанию к моему представлению. Колонка одна. Без изменений. Повторения как были так и есть(
Елена, не фильтр, сам запрос должен быть таким. В представлении какой сервис запроса используется?
Тот же сервис что и для всего раздела
Раздел в общем
А в представлении Не отмечен должен быть просто перечень сотрудников
У реестра на событие OnActiveViewChanged(DataGrid, OldDataGridView) нужно прописать примерно следующее:
var select = dlData.Dataset.SelectQuery.Items(0); select.IsDistinct = (DataGrid.ActiveView.Name == 'Ваше представление');
прописала:
var select = dlData.Dataset.SelectQuery.Items(0); select.IsDistinct = (DataGrid.ActiveView.Name == 'ActiveGridView3');
Дубли не пропали, зато при переходе на другие представления в разделе данные начали дублироваться по очень много раз
Покажите, пожалуйста, скриншот представления ActiveGridView3 и запросы, которые идут на сервер при переключении на это представление и при уходе из него. Под профайлером сможете посмотреть запросы?
SELECT DISTINCT [tbl_Contact].[ID] AS [ID], [tbl_Contact].[Name] AS [ContactName], [tbl_AttendenceJob].[P_FAM] AS [P_FAM], CAST('19700101 ' + CONVERT(VARCHAR(20), [tbl_AttendenceJob].[R_DT], 108) AS DATETIME) AS [R_DT], [tbl_AttendenceJob].[R_H] AS [R_H], CAST(CONVERT(VARCHAR(8), [tbl_AttendenceJob].[R_DT], 112) AS DATETIME) AS [Day], [tbl_Contact].[ContactTypeID] AS [ContactTypeID], FROM [dbo].[tbl_Contact] AS [tbl_Contact] LEFT OUTER JOIN [dbo].[tbl_AttendenceJob] AS [tbl_AttendenceJob] ON [tbl_AttendenceJob].[P_FAM] = [tbl_Contact].[Name]
Елена, колонки
[tbl_AttendenceJob].[P_FAM] AS [P_FAM], CAST('19700101 ' + CONVERT(VARCHAR(20), [tbl_AttendenceJob].[R_DT], 108) AS DATETIME) AS [R_DT], [tbl_AttendenceJob].[R_H] AS [R_H], CAST(CONVERT(VARCHAR(8), [tbl_AttendenceJob].[R_DT], 112) AS DATETIME) AS [Day],
дают Вам Ваши дубли. Скройте их в представлении, тогда они не будут включены в запрос. Поскольку основной таблицей выборки является таблица контактов, в которой нет дублей, то логику по изменению свойства IsDistinct можно убрать.
Но вообще-то мне кажется странным показывать в представлении "Не отмечен" всех контактов, даже если они не были замечены в tbl_AttendenceJob. Я бы добавила фильтр
where exists (select Id from [dbo].[tbl_AttendenceJob] AS [tbl_AttendenceJob] where [tbl_AttendenceJob].[P_FAM] = [tbl_Contact].[Name])
И еще плохо, что tbl_AttendenceJob ссылается на таблицу контактов по имени, а не по Id.
Все колонки кроме Contactname и так скрыты
Оставила в скрипте только:
function grdDataOnActiveViewChanged(DataGrid, OldDataGridView) { dlData.Dataset.Close(); dlData.Dataset.Open();
Данные дублируются((
Я вывожу простой список контактов, потому что потом к нему удобно применять созданные фильтры по условиям прихода
Я думала, что из запроса отключаются все колонки, кроме тех, что отображены, но, оказывается, не все. Попробуйте так:
var columns = dlData.Dataset.SelectQuery.Items(0).Columns; for (var i = 0; i < columns.Count; i++) { columns[i].IsEnabled = (columns[i].CanDisable) && columns[i].ColumnAlias == "ContactName" }
Итак прописала
function grdDataOnActiveViewChanged(DataGrid, OldDataGridView) { dlData.Dataset.Close(); var columns = dlData.Dataset.SelectQuery.Items(0).Columns; for (var i = 0; i < columns.Count; i++) { columns[i].IsEnabled = (columns[i].CanDisable) && columns[i].ColumnAlias == "ContactName" } dlData.Dataset.Open();
При переключении представлений выдает ошибку
Ошибка выполнения метода 'grdDataOnActiveViewChanged'. 'undefined' - есть null или не является объектом
Нужно найти, что из этого всего undefined, я по памяти писала, проверить негде, поставьте после второй строчки debugger; и посмотрите.
не понимает строку
columns[i].IsEnabled = (columns[i].CanDisable) && columns[i].ColumnAlias == "ContactName"
а именно CanDisable
А разве таким кодом не отключаться все колонки кроме ContactName? а как же остальные представления, где эти колонки нужны?
Как делать проверку представления, мы же уже писали выше.
Странно, что ругается на это свойство, оно должно быть
http://terrasoft.ru/sdk/IColumn__CanDisable@[out,_retval]_VARIANT_BOOL_…
Попробуйте пока без него:
if (DataGrid.ActiveView.Name == 'ActiveGridView3') { columns[i].IsEnabled = (columns[i].ColumnAlias == "ContactName"); }
Хотя так не очень хорошо, для других представлений нам не понятно, какие колонки включать.
var columnsToDisable = new Array( "P_FAM", "R_DT","R_H", "Day", "ContactTypeID"); var isDisabedView = (DataGrid.ActiveView.Name == 'ActiveGridView3'); var columns = dlData.Dataset.SelectQuery.Items(0).Columns; for (var i = 0; i < columnsToDisable.length; i++) { columns.ItemsByAlias(columnsToDisable[i]).IsEnabled = !isDisabedView; }
function grdDataOnActiveViewChanged(DataGrid, OldDataGridView) { dlData.Dataset.Close(); var columns = dlData.Dataset.SelectQuery.Items(0).Columns; for (var i = 0; i < columns.Count; i++) { if (DataGrid.ActiveView.Name == 'ActiveGridView3') { columns[i].IsEnabled = (columns[i].CanDisable)&&columns[i].ColumnAlias == "ContactName"; } } dlData.Dataset.Open(); }
Ругаться перестала, дубли как были так и есть=((
function grdDataOnActiveViewChanged(DataGrid, OldDataGridView) { dlData.Dataset.Close(); var columnsToDisable = new Array( "P_FAM", "R_DT","R_H", "Day","ContactTypeID"); var isDisabedView = (DataGrid.ActiveView.Name == 'ActiveGridView3'); var columns = dlData.Dataset.SelectQuery.Items(0).Columns; for (var i = 0; i < columnsToDisable.length; i++) { columns.ItemsByAlias(columnsToDisable[i]).IsEnabled = !isDisabedView; } dlData.Dataset.Open(); }
Дубли остались
Для второго куска кода какой запрос показывает профайлер?
К сожалению, сейчас не могу попасть в Profiler и посмотреть запросы.
А взможно ли создать фильтр по ContactName, который б искал повторняющиеся данные?
Или же сгруппировать данные на этом представлении?
Вопрос решился!!!!!!
В SelectQuery в поле R_ID стояла галка "всегда выберать в запросе", поэтому данные дублировались!
Большое спасибо за помощь!
Елена, смотрите, если у Вас есть набор данных, как Вы писали в самом начале
Иванов Вход
Петров Вход
Сидоров Выход
Иванов Выход
и Вы хотите, чтобы вывелись только фамилии, если запрос будет вида:
select Name from Contact group by Name
то, получите ожидаемый результат, но если Вы напишете
select Name, Action from Contact group by Name
то что тогда следует отобразить во второй колонке для Иванова Вход или Выход? Вывод: наша проблема в том, что в запросе фигурирует число колонок, большее, чем требуется, а точнее даже то, что в них разные значения.
А не лучше избавиться от дублей в таблице где они образовались. Плюс пересмотр работы логики Грида с разделением на более мелкие сущности. И все. Ведь все способы которые вы предлагаете ведут только к одному Грид рано или поздно будет тяжелым и данные из него уже при этом по кнопке "Удалить все" сделать уже нельзя будет. В Гридах запросы должны быть очень легкие без всяких DISCINT, GROUP BY, ПодЗапросов. Как только в Гриде появляются колонки с подзапросами это уже красный флаг для пересмотра работы Грида и структуры данных. Так как любая задача должна биться на мелкие сущности. Закон жизни :)
"Власов Михаил Викторович" написал:А не лучше избавиться от дублей в таблице где они образовались
Вы предлагаете избавиться от дублей по фамилии в таблице журнала посещений? Смелое решение :)
"Власов Михаил Викторович" написал:Грид рано или поздно будет тяжелым и данные из него уже при этом по кнопке "Удалить все" сделать уже нельзя будет
Ну разумеется, если конечная цель удалить все данные, то уж лучше тогда и не затевать подобной работы.
Согласна, можно было сделать проще изначально создавая таблицу журнала посещений, но предложите более легкий вариант решения текущей задачи. Вариант с удалением дублей не предлагать.
А можно пожалуйста увидеть сам запрос целиком в виде TXT файла. Я думаю там вся загвоздка (образующая дубли) в Левых соединениях. Если перенести Левое соединение образующая дубли в Where EXISTS то это и будет решение проблемы. Но для правильного ответа пожалуйста еще раз повторюсь выложите SQL запрос в виде TXT. Только полный запрос. Не кусок кода. Спасибо!!!
Отчасти Вы правы, только я бы вместо exists сделала inner соединение, но ни то ни другое в данном случае невозможно, т.к. этот же запрос используется в этом же реестре, только другом представлении для отображения всех данных и там нужно левое соединение. Текста запроса у меня нет. Все, что есть, вверх по теме.
Уважаемая Ольга я просил и прошу автора Сообщения выложить свой SQL запрос в данную тему. Где я думаю решения вопроса не будет таким сложным после рассмотрения SQL запроса.
Уважаемый Михаил, ни в одном из Ваших сообщений я не увидела личного обращения к Елене по имени, поэтому уж простите, что ответила.
"Перепечай Елена" написал:Вопрос решился!!!!!!
"Власов Михаил Викторович" написал:Где я думаю решения вопроса не будет таким сложным после рассмотрения SQL запроса.
Михаил, высылать SQL запрос я не вижу смысла так как вопрос действительно решился.
Дублирование имен контактов в таблице Посещения неизбежно, так как информация в других колонках меняется. Каждый день отмечаются о посещении одни и те же люди, проставляется только разное число и время.
Никаких дополнительных подзапросов я не делала, так как причина была в том, что в одном из полей стояла галка "Всегда выбирать в запросе", я ее не заметила (моя вина=)). Поэтому выбирались имена контактов и данные из другой колонки. В этом была причина дублирования.