Какой SQL-запрос или представление покажет "динамические столбцы"

У меня есть таблица данных, и я разрешаю людям добавлять в эту таблицу метаданные.

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

Data Table
   DataID
   Data

Meta Table
   DataID
   MetaName
   MetaData

Поэтому, если бы им нужна была таблица, в которой хранятся данные, дата и имя, у меня были бы данные в таблице данных, и слово «Дата» в мета-имени, и дата в метаданных, и еще одна строка в таблица meta с «Name» в метаниме и именем в метаданных.

Теперь мне нужен запрос, который берет информацию из этих таблиц и представляет ее так, как если бы она поступала из одной таблицы с двумя дополнительными столбцами «Данные» и «Имя», чтобы для клиента это выглядело так, как будто есть одна таблица с их настраиваемыми столбцами. :

MyTable
   Data
   Date
   Name

Или, другими словами, как мне отсюда уйти:

Data Table
   DataID        Data
   1             Testing!
   2             Hello, World!

Meta Table
   DataID        MetaName         MetaData
   1             Date             20081020
   1             Name             adavis
   2             Date             20081019
   2             Name             mdavis

Сюда:

MyTable
   Data          Date             Name
   Testing!      20081020         adavis
   Hello, World! 20081019         mdavis

Много лет назад, когда я делал это в MySQL с использованием PHP, я выполнил два запроса: первый для получения дополнительных метаданных, а второй - для их объединения. Я надеюсь, что в современных базах данных есть альтернативные методы решения этой проблемы.

Относится к варианту 3 этот вопрос.

-Адам

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
4
0
9 755
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

SELECT DataTable.Data AS Data, MetaTable.MetaData AS Date, MetaTable.MetaName AS Name
FROM DataTable, MetaTable
WHERE DataTable.DataID = MetaTable.DataID

Вероятно, вы захотите добавить дополнительное предложение (AND Data = 'some value'), чтобы возвращать строки, которые интересуют пользователя.

AFAIK, вы можете сделать это на стороне сервера только с помощью динамической хранимой процедуры SQL.

Фактически код, который вы хотите генерировать динамически, выглядит следующим образом:

SELECT [Data Table].*
    ,[MyTable Date].MetaData
    ,[MyTable Name].MetaData
FROM [Data Table]
LEFT JOIN [MyTable] AS [MyTable Date]
    ON [MyTable Date].DataID = [Data Table].DataID
    AND [MyTable Date].MetaName = 'Date'
LEFT JOIN [MyTable] AS [MyTable Name]
    ON [MyTable Name].DataID = [Data Table].DataID
    AND [MyTable Name].MetaName = 'Name'

И вот код для этого:

DECLARE @sql AS varchar(max)
DECLARE @select_list AS varchar(max)
DECLARE @join_list AS varchar(max)
DECLARE @CRLF AS varchar(2)
DECLARE @Tab AS varchar(1)

SET @CRLF = CHAR(13) + CHAR(10)
SET @Tab = CHAR(9)

SELECT @select_list = COALESCE(@select_list, '')
                        + @Tab + ',[MyTable_' + PIVOT_CODE + '].[MetaData]' + @CRLF
        ,@join_list = COALESCE(@join_list, '')
                        + 'LEFT JOIN [MyTable] AS [MyTable_' + PIVOT_CODE + ']' + @CRLF
                            + @Tab + 'ON [MyTable_' + PIVOT_CODE + '].DataID = [DataTable].DataID'  + @CRLF
                            + @Tab + 'AND [MyTable_' + PIVOT_CODE + '].MetaName = ''' + PIVOT_CODE + '''' + @CRLF
FROM (
    SELECT DISTINCT MetaName AS PIVOT_CODE
    FROM [MyTable]
) AS PIVOT_CODES

SET @sql = 'SELECT [DataTable].*' + @CRLF
            + @select_list
            + 'FROM [DataTable]' + @CRLF
            + @join_list
PRINT @sql
--EXEC (@sql)

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

Итак, это вариант с двумя запросами, где я сначала выясняю, какие «динамические» столбцы мне нужно извлечь из метатаблицы, а затем составляю запрос из этих результатов?

Adam Davis 20.10.2008 23:41

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

Cade Roux 20.10.2008 23:44

Спасибо, это было бы полезно. Не могли бы вы также упомянуть, на каком SQL-сервере вы знаете, что это работает?

Adam Davis 20.10.2008 23:56

Это будет работать на SQL Server, используя трюк SELECT для создания динамических строк без курсора. На других платформах есть CONCAT, или вам, возможно, придется использовать курсор. Сгенерированный им запрос должен быть в достаточной степени ANSI (вам нужно будет следить за плохими символами в именах таблиц или в MetaName).

Cade Roux 21.10.2008 00:01
Ответ принят как подходящий

Вы хотите развернуть каждую из строк пары имя-значение в MyTable ... Попробуйте этот sql:

DECLARE @Data   TABLE (
    DataID      INT IDENTITY(1,1)   PRIMARY KEY,
    Data        VARCHAR(MAX)
)

DECLARE @Meta   TABLE (
    DataID      INT ,
    MetaName    VARCHAR(MAX),
    MetaData    VARCHAR(MAX)
)

INSERT INTO @Data
SELECT 'Data'

INSERT INTO @Meta
SELECT 1, 'Date', CAST(GetDate() as VARCHAR(20))
UNION
SELECT 1, 'Name', 'Joe Test'

SELECT * FROM @Data

SELECT * FROM @Meta

SELECT 
    D.DataID,
    D.Data,
    MAX(CASE MetaName WHEN 'Date' THEN MetaData ELSE NULL END) as Date,
    MAX(CASE MetaName WHEN 'Name' THEN MetaData ELSE NULL END) as Name
FROM
    @Meta M
JOIN    @Data D     ON M.DataID = D.DataID  
GROUP BY
    D.DataID,
    D.Data

Подробнее о CASE лом SQL. 4guysfromrolla.com/webtech/102704-1.shtml

jason saldo 20.10.2008 23:53

Как лучше всего запросить результат? Пример: SELECT * FROM Table WHERE Name = 'Joe Test' Нужно ли мне сохранять первые результаты и запрашивать эту таблицу? Или есть способ внедрить фильтр WHERE на первом проходе?

182764125216 09.11.2011 03:26

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