VB / SQL - Как отфильтровать DataGridView из объединенной таблицы с несколькими совпадениями - PullRequest
0 голосов
/ 28 января 2020

Я использую SQL Server и Visual Studio 2019.

Я ищу совет относительно лучшего способа фильтрации списка моих документов (в DataGridView) на основе того, в каком представлении они отображаются.

У меня есть 3 таблицы базы данных, показанные ниже:

Tables

Я упростил мою таблицу документов для этого поста, но есть много деталей для каждого документа, отображаемого в DataGridView .

Я заполняю DataTable , который я использую для яблока в DataView , который затем используется в моем DataGridView DataSource . В пределах SQL, который заполняет DataTable У меня есть пользовательский столбец , который использует JOIN для определения View , в котором появляется каждый документ, позже я отфильтрую список документов на основе пользовательского столбца 1037 *. Это действительно работает, только если документ отображается только в 1 представлении, иначе JOIN извлекает несколько записей документа для покрытия каждого View соответствия. (надеюсь, это имеет смысл).

Я упростил Просмотр таблицы и для этого поста, Просмотр может содержать Подвиды , если вы например:

View 1
 > Sub View 1
 > Sub View 2
    > Child of Sub View 2

Это означает, что Документ может появляться более одного раза в Представлении , как это может появляться в различных Подвидах .

Интересно, лучше ли мне продолжить извлечение пользовательского столбца 1062 * или мне нужно выполнить совершенно новый запрос SQL и даже создание новой DataTable / DataView на основе таблицы View .

Некоторые из наших сотрудников являются удаленными, а некоторые проекты могут содержать тысячи документов , поэтому я хочу убедиться, что я использовал самый надежный метод, но также тот, который вызовет наименьшую задержку при получении информации и предоставит пользователю лучший опыт.

Надеюсь, я объяснил вам все достаточно ребята, чтобы получить список того, что я пытаюсь достичь.

Спасибо заранее, и я бы Пожалуйста, примите во внимание любую помощь в этом.

>
>
Edit - Following first answer post:

Как вы говорите, я, вероятно, недостаточно объяснил, поэтому я собрал наглядный пример того, чего я пытаюсь достичь.

Когда проект загружен, все документы перечислены, TreeView не был нажат, поэтому фильтр не применяется . Все документы перечислены:

View 1

Если пользователь нажимает « View 1> Sub View 2 » в TreeView it фильтры на основе данных в CustomJOINColumn , см. Ниже:

View 2

Если пользователь нажимает « Вид 1> Подвид 1 » или « Другой вид> Документы » на TreeView это снова фильтры на основе данные в CustomJOINColumn , см. ниже:

View 34

Как вы можете видеть Документ D001 появился в 3 различных вида / вложенных вида .

Проблема показана на первом изображении. Документ D001 указан в списке 3 раза, поскольку он связан с 3 видами / вложенными видами. Я только хочу, чтобы Документ D001 до появлялся один раз в первом списке , но когда соответствующий Узел в TreeView щелкнул по нему Фильтрует правильно, как показано.

Надеюсь, это имеет смысл.

1 Ответ

0 голосов
/ 29 января 2020

Могут быть некоторые детали вашего случая, которые указывают на другое решение, но из того, что у вас есть здесь, звучит так, как будто вы должны отбросить специальный столбец, отбросить полное заполнение с фильтрацией и реализовать целевое заполнение для вашего DataGridView. Это даже не включает в себя большую часть изменений, небольшую модификацию, а не серьезную переписку.

Почему? Потому что, особенно если у вас есть удаленные работники в глобальной сети, снижение производительности при загрузке полного списка документов будет очень большим, если у вас много больших представлений. Сосредоточенная загрузка позволяет вам тратить время на загрузку только соответствующих деталей документа. Вы получаете первые 500 мс или около того "бесплатно" с пользователями, но если вы потратите хотя бы 30 секунд на загрузку и фильтрацию, они подумают, что это сбой. И ваше приложение занимает больше памяти, когда оно заполнено сеточными строками деталей документа, которые вы никогда не будете использовать. Кроме того, как вы уже обнаружили, придумать схему фильтрации, основанную на членстве в произвольном количестве перекрывающихся групп, действительно сложно, а целевую нагрузку действительно легко.

Так как это сделать? Сначала go к вашему DataSet и измените адаптер таблицы с помощью «Добавить» -> «Запрос». Вы определите новый запрос, который использует параметр (@View) и возвращает данные в том же формате, что и оригинал, но только для документов в этом представлении. Дайте ему очевидное имя, например, когда оно предлагает имя «Fill», сделайте его «FillByView»

Далее, возьмите копию кода в вашем событии Form_Load, которое заполняет сетку (что-то вроде tadaptDocs.Fill (tblDocList )) и закомментируйте его там, но поместите копию в событие Change для элемента управления, в котором пользователь выбирает представление. Измените его с «Fill» на «FillByView» и добавьте параметр @View.

Возможно, вы захотите, чтобы событие Form_Load установило представление на последний выбранный вид (сохраните в My.Settings) или на первый вид в списке, который вызовет событие Change и заполнит DataGridView начальным набором документов.

Теперь, каждый раз, когда пользователь выбирает новое представление, сетка загружается только с теми документами в этом представлении, независимо от того, в каких других представлениях они могут находиться.

При сохранении изменений через «Обновление» VB автоматически применяет изменения к базовым данным, вам не нужно беспокоиться о том, что он усечет вашу таблицу базы данных только до документов в это мнение. Это делает внутреннее различие между записями, которые были удалены, и записями, которые никогда не загружались. Вам также не нужно создавать новые версии методов Update, Insert или Delete в TableAdapter, только Fill Требуется новая версия, которая учитывает View.

EDIT: следующие дополнения в ответ на дополнения, разъясняющие проблема

Звучит так, как будто все еще требуется сфокусированная нагрузка, но только когда пользователь выбирает вид. Ваш первоначальный вид должен быть «заполнить все», но изменен для удаления дубликатов. Если у вас есть много деталей в сетке, вы, вероятно, захотите разбить это на 2 части с помощью CTE, пример следует

;WITH cteCust as (
   SELECT D.DocID as DocID, D.docNum , D.docTitle , V.CustJoinName as CustJoin
    , ROW_NUMBER() OVER (PARTITION BY D.docNum ORDER BY V.viewTitle) as ViewRank
   FROM #tblDoc as D  LEFT OUTER JOIN #MapDocView as M on D.DocID = M.DocID
        OUTER APPLY fnGetCustJoinName(M.ViewID) as V 
) SELECT C.DocID , C.docNum , C.docTitle , C.CustJoin , D.docOther 
FROM cteCust as C INNER JOIN #tblDoc as D ON C.DocID = D.DocID 
WHERE ViewRank = 1
ORDER BY D.docNum 

Несколько элементов объяснения этого медведя, ответьте в комментариях, если вам нужно больше детали

cteCust извлекает информацию о базовом документе и добавляет пользовательские столбцы объединения, я не уверен, как вы это делаете, но функция с табличными значениями - это один из способов, и я ее использовал для простоты замените все, что вы используете. Вы сказали, что было много информации о документе, это позволяет вам работать только с основными деталями и t ie с другими материалами позже. Мы используем LEFT OUTER JOIN в таблице карт, потому что вы хотите, чтобы документы без представления все еще отображались в нефильтрованном списке.

ViewRank - это то, как вы Избавившись от дубликатов, разделив функцию ROW_NUMBER на Документы, вы получите только первое представление, в котором оно находится. В выделенной заливке вы хотите, чтобы представление фильтровалось, но вы сказали, что первоначальная заливка должна быть только одним представлением, поэтому каждый документ отображается только один раз.

Обратите внимание, что последний SELECT связывает его с таблицей документов, так что вы можете выбрать дополнительные поля.

ПРИМЕЧАНИЕ: В вашем примере у вас есть простая модель членства - вы хотите, чтобы Документы, принадлежащие указанному c представлению, не были иерархическим, где вы хотите, чтобы все документы в представлении и все вложенные представления ( то есть D006 находится в Утверждено , но не отображается при выборе родительского элемента Документы в примере 3 вашего обновленного вопроса). Если эти требования меняются, и ваши клиенты хотят рекурсивное сканирование членства, вы должны опубликовать его в качестве второго вопроса, этот вопрос и ответы уже огромны, и вы получите на sh взгляд, если это новый вопрос. Опубликуйте здесь ссылку, но задайте ей новый вопрос.

...