Матричная таблица SQL

У меня есть три таблицы:

  • Таблица tCity

    (Id int, City nvarchar(50))
    
  • Таблица tLocation

    (Id int, Location nvarchar(50))
    
  • Таблица tCityLocation

    (Id int, CityId int, LocationId int)
    

Я хотел бы создать матричную таблицу, как на изображении ниже.

Если город относится к location->, то в соответствующей ячейке таблицы будет записан символ X.

Я хотел бы узнать о каком-либо изощренном подходе, как его достичь. У меня была проблема с аналогичной логикой, и я обрабатывал ее итерацией в курсорах с динамически добавленным столбцом в таблицу набора результатов.

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

Спасибо.

Какая у тебя РБД?

gotqn 20.01.2023 07:53

Это плохая структура БД. Континенты и страны не должны храниться в одной таблице.

Jonas Metzler 20.01.2023 08:38

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

Dale K 20.01.2023 10:16

Матричных таблиц нет ни в одной базе данных. Таблицы — это не электронные таблицы. Они представляют отношение между элементами, хранящимися в их столбцах.

Panagiotis Kanavos 20.01.2023 10:21

Если вы хотите создать матричное представление для отображения, проще перенести данные на клиенте. В SQL вам придется заранее определить столбцы (отношения не могут иметь произвольные типы столбцов/сущностей) и использовать предложение PIVOT. Однако это все еще не настоящая матричная таблица. С другой стороны, в HTML вы можете легко создать матрицу из List<(x,y,value)>, используя цикл для создания элементов <th>, <tr> и <td>.

Panagiotis Kanavos 20.01.2023 10:26
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
5
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это должно быть что-то вроде этого:

DECLARE @DymanimcTSQLSatement NVARCHAR(MAX)
       ,@DynamicColumns NVARCHAR(MAX);

SET @DynamicColumns = STUFF
                      (
                        (
                            SELECT ',' + QUOTENAME([Location])
                            FROM tLocation
                            GROUP BY [Location] 
                            ORDER BY [Location] 
                            FOR XML PATH(''), TYPE
                        ).value('.', 'NVARCHAR(MAX)')
                        ,1
                        ,1
                        ,''
                     );

SET @DymanimcTSQLSatement = N'
SELECT *
FROM
(
    SELECT L.Location
          ,C.City
          ,1
    FROM tCityLocation CL
    INNER JOIN tLocation L
        ON CL.[LocationId] = L.[id]
    INNER JOIN tCity C
        ON CL.[CityId] = C.[id]
) DS (country, city, value)
PIVOT
(
    MAX([value]) FOR [country] IN (' + @DynamicColumns +')
) PVT;';

EXECUTE sp_executesql @DymanimcTSQLSatement;

и вот данные, которые я использовал:

-- Creating Table tCity
CREATE TABLE tCity (
    Id int,
    City nvarchar(50)
);

-- Populating Table tCity with 10 records
INSERT INTO tCity (Id, City) VALUES (1, 'New York');
INSERT INTO tCity (Id, City) VALUES (2, 'Los Angeles');
INSERT INTO tCity (Id, City) VALUES (3, 'Paris');
INSERT INTO tCity (Id, City) VALUES (4, 'Tokyo');
INSERT INTO tCity (Id, City) VALUES (5, 'Sydney');
INSERT INTO tCity (Id, City) VALUES (6, 'Philadelphia');
INSERT INTO tCity (Id, City) VALUES (7, 'Rio de Janeiro');
INSERT INTO tCity (Id, City) VALUES (8, 'Cape Town');
INSERT INTO tCity (Id, City) VALUES (9, 'Beijing');
INSERT INTO tCity (Id, City) VALUES (10, 'Singapore');

-- Creating Table tLocation
CREATE TABLE tLocation (
    Id int,
    Location nvarchar(50)
);

-- Populating Table tLocation with 10 records
INSERT INTO tLocation (Id, Location) VALUES (1, 'United States');
INSERT INTO tLocation (Id, Location) VALUES (2, 'United States');
INSERT INTO tLocation (Id, Location) VALUES (3, 'France');
INSERT INTO tLocation (Id, Location) VALUES (4, 'Japan');
INSERT INTO tLocation (Id, Location) VALUES (5, 'Australia');
INSERT INTO tLocation (Id, Location) VALUES (6, 'United States');
INSERT INTO tLocation (Id, Location) VALUES (7, 'Brazil');
INSERT INTO tLocation (Id, Location) VALUES (8, 'South Africa');
INSERT INTO tLocation (Id, Location) VALUES (9, 'China');
INSERT INTO tLocation (Id, Location) VALUES (10, 'Singapore');

-- Creating Table tCityLocation
CREATE TABLE tCityLocation (
    Id int,
    CityId int,
    LocationId int
);


INSERT INTO tCityLocation (Id, CityId, LocationId)
SELECT 
    ROW_NUMBER() OVER (ORDER BY tCity.Id), 
    tCity.Id, tLocation.Id
FROM tCity 
JOIN tLocation 
ON tCity.Id = tLocation.Id;

Идея состоит в том, чтобы построить динамический PIVOT, где столбцы PIVOT — это уникальные страны (в вашем случае местоположения). Если ваш SQL Server поддерживает STRING_AGG, вы можете сделать это по-другому:

SELECT @DynamicColumns = STRING_AGG(CAST(QUOTENAME([Location]) AS VARCHAR(MAX)), ',') WITHIN GROUP (ORDER BY [Location])
FROM
(
    SELECT DISTINCT [Location]
    FROM tLocation
) DS ([Location]);

Было бы здорово, если бы ваш ответ также содержал объяснение того, как это работает в дополнение к решению.

Dale K 20.01.2023 10:18

Уловка XML больше не нужна в поддерживаемых версиях SQL Server. Ответ было бы легче понять, если бы использовался STRING_AGG

Panagiotis Kanavos 20.01.2023 10:22

Лучший способ ответить на этот вопрос — использовать стержень

Сначала я получаю список Location of table Location

Во-вторых, я получаю список Расположение таблицы tLocation Для использования в выборе Потому что мне нужно использовать ISNULL для замены нуля пробелом

после использования поворота для получения результата

результат: строки включают список городов, а столбцы включают местоположение

город Азия CRez Респ. Европа Франция ГБ Германия Япония Северная Америка США Нью-Йорк Икс Икс Прага Икс Икс Икс Лондон Икс Икс Токио Икс Икс
--Get List Columns for Pivot

DECLARE @cols AS NVARCHAR(MAX),@scols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Location)  from tLocation
                 FOR XML PATH(''), TYPE  ).value('.', 'NVARCHAR(MAX)')   ,1,1,'' )
 
--can to use below Code for Replace null with space

select @scols = STUFF((SELECT distinct ',ISNULL(' + QUOTENAME(Location) +','' '') as '+  QUOTENAME(Location)
                 from tLocation  FOR XML PATH(''), TYPE  ).value('.', 'NVARCHAR(MAX)')  ,1,1,'')
 
 set @query = 'SELECT  city ,'+@scols+' from 
             (
                select cl.CityId,c.City,l.Location,''X'' as Value from tCityLocation cl
                inner join tCity c on cl.CityId=c.Id
                inner join tLocation l on cl.LocationId=l.Id
            ) x
            pivot 
            (
               max( value)  for Location in (' + @cols + ')
            ) p 
            order by CityId
            '

execute(@query)

Вы можете вставить основные данные со следующими кодами


create table tCity(Id int, City nvarchar(50))

create table tLocation(Id int, Location nvarchar(50))

create table tCityLocation(Id int, CityId int, LocationId int)

insert into tCity
(id,City)
select 1 as id,'NY' union all select 2 as id,'Prague'
union all select 3 as id,'London' union all select 4 as id,'Tokio'

insert into tLocation (id,Location)
select 1,'USA' union all select 2,'CRezah Rep.' union all select 3,'France' union all select 4,'GB'
union all select 5,'Germany' union all select 6,'Europe' union all select 7,'N.America'
union all select 9,'Asia' union all select 10,'Japan'

insert into tCityLocation
(id,CityId,LocationId)
select 1,1,1 union all select 2,1,7 union all select 3,2,2 union all select 4,2,6 union all select 5,3,4 union all
select 6,3,6 union all select 7,4,9 union all select 8,4,10 

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

Dale K 20.01.2023 10:17

Также при предоставлении ответа, пожалуйста, предоставьте объяснение в дополнение к рабочему коду.

Dale K 20.01.2023 10:17

Я отредактировал этот пост, если у этого поста есть проблемы, пожалуйста, скажите мне. @Дейл К.

Hemin sadeghi 24.01.2023 22:17

Другие вопросы по теме