2016-10-08 1 views
1

Пожалуйста, мне нужна помощь. Я создал таблицу Users (колонки UserID, UserName) и таблицу Project (столбцы ProjectID, ProjectName) и таблицу моста, в которой отображаются имя проекта и имя пользователя.Как преобразовать отношение сущностей ко многим ко многим в табличное представление в SQL?

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

Мост таблица выглядит следующим образом:

enter image description here

ли доступны, чтобы сделать вид даты, как это и как?

enter image description here

Обратите внимание на проекты и USERNAMES не являются фиксированными, они динамичны, они добавляют из форм в VB.NET.

+0

https://www.tutorialspoint.com/sql/sql-using-joins.htm – Plutonix

+0

@michael raouf У вас есть определенное число столбцов? то есть сколько максимального пользователя может иметь один проект? –

+0

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

ответ

0

Возможно, я предлагаю следующее решение (пожалуйста, не судите строго, это просто идея): вместо того, чтобы иметь фиктивный «Имя пользователя» в качестве имени столбца в вашей первой строке, почему бы не поставить туда настоящих имен пользователей и да/нет на перекрестке строк/столбцов для каждого пользователя/проекта. См. Рисунок ниже. Это общий вид вида в разных таблицах членства или таблицах счисления игроков (но они имеют одинаковые имена по вертикали и по горизонтали).

Proposed dynamic project membership view

Я вставил членство записи тестов, так что вы видите Марк является членом во всех проектах, в то время как Брайан только в SQL.

Этот динамический SQL производит вышеуказанный вывод:

DECLARE @dynPivotSQL AS NVARCHAR(MAX) 
DECLARE @pivotColNames AS NVARCHAR(MAX) 
DECLARE @pivotColNamesMin AS NVARCHAR(MAX) 

-- get distinct username for column headers 
SELECT @pivotColNames= ISNULL(@pivotColNames + ',','') 
     + QUOTENAME(UserName), 
     @pivotColNamesMin= ISNULL(@pivotColNamesMin + ',','') 
     + 'min(' + QUOTENAME(UserName) +') as ' + QUOTENAME(UserName) 
FROM (SELECT DISTINCT UserName, UserID FROM Users) AS U 

SET @dynPivotSQL = N' 
with cte as (
    select p.ProjectName,u.UserName,IsMember=1 from ProjectsUsers pu 
    join Projects p on p.ProjectID = pu.FK_ProjectID 
    join Users u on u.UserID = pu.FK_UserID 
) select ProjectName, ' + @pivotColNamesMin + ' from cte 
pivot (
    min(IsMember) for UserName in (' + @pivotColNames + ') 
) pvt 
group by ProjectName '   

EXEC sp_executesql @dynPivotSQL 

Примечание, так как ваше требование, чтобы иметь динамические списки проектов/пользователей я должен был использовать динамический SQL для создания динамического списка столбцов для Т- SQL PIVOT, который обычно работает с жестко закодированными/статическими значениями/именами столбцов.

Обратите внимание, что в используемом блоке используется трюк min (IsMember), потому что для pivot требуется некоторая функция агрегации, но мы не можем выполнить min (UserName), потому что оно действительно вернет минимальное имя в наборе конкретного проекта имена участников.

@pivotColNamesMin - еще один трюк, теперь для GROUP BY, потому что он не будет работать, если все возвращенные столбцы не входят в группу по списку или не находятся внутри агрегатной функции.

Я уверен, что вы можете подать предложенный источник данных в свою сетку данных, а во время некоторых событий ItemDataBound или подобных событий вы можете изменить эти «1» знаки членства на пользовательские строки или изображения с помощью «ДА» или чего-либо подобного. Но для того, чтобы это работало, ваша databrid не должна использовать жестко заданные имена столбцов и иметь возможность динамически загружать их из фактического набора результатов.

Я проверил свой запрос на SQL Server 2008 R2. Дайте мне знать, если это приемлемое решение, чтобы я мог перестать его настраивать.

НТН

-1

Я создал таблицу в SQL Server с записями вы показали, и консольное приложение VB.NET с этим кодом:

Option Infer On 
Imports System.Data.SqlClient 

Module Module1 

    Sub Main() 
     Dim csb As New SqlConnectionStringBuilder With {.DataSource = ".\SQLEXPRESS", .InitialCatalog = "testing", .IntegratedSecurity = True} 
     Dim projectsUsers As New Dictionary(Of String, List(Of String)) 
     Using sqlConn As New SqlConnection(csb.ConnectionString) 
      Dim sql = "SELECT [project], [user] FROM ProjectUser" 
      Using sqlCmd As New SqlCommand(sql, sqlConn) 
       sqlConn.Open() 
       Using rdr = sqlCmd.ExecuteReader() 
        If rdr.HasRows Then 
         While rdr.Read() 
          Dim project = rdr.GetString(0) 
          Dim user = rdr.GetString(1) 
          If projectsUsers.ContainsKey(project) Then 
           projectsUsers(project).Add(user) 
          Else 
           projectsUsers.Add(project, New List(Of String) From {user}) 
          End If 
         End While 
        End If 
       End Using 
      End Using 
     End Using 

     ' adjust output as required 
     For Each kvp In projectsUsers 
      Console.WriteLine(kvp.Key & ": " & String.Join(", ", kvp.Value)) 
     Next 

     Console.ReadLine() 

    End Sub 

End Module 

и получил этот результат:

SQL: Майкл, Сэм, Марк
C#: Сэм, Марк
Joomla: Mark

Вы дзю st необходимо изменить метод для отображения вывода по желанию.

+0

Спасибо, Андрей, я вижу, вы используете VB.net чтобы получить результат, то, что я ищу, чтобы сделать его SQL Query для загрузки его в datatable, а затем добавить этот datatable в datagridview, все это легко для меня сделать, но просто хочу знать, может ли оно быть прямым в sql как запрос? –

+0

@michaelraouf Пожалуйста, отредактируйте свой вопрос, чтобы спросить, что вы на самом деле хотите задать. –

0

Спасибо вам, ребята, я нашел другое решение, выбрать название проекта из комбо-бокс и в таблице показаны имена пользователей, что они в этом проецирует его не выглядит как то, что я хочу в сначала, но это решение более просто: D еще раз спасибо

+0

спасибо за возвращение с обратной связью! Обратите внимание, что в будущем, если вам нужно повернуть строки в столбцы, используйте предложение PIVOT и постройте на нем. – andrews